home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / manchester / 2.2 / actors / SMACKv1.1.st < prev   
Text File  |  1993-07-24  |  99KB  |  3,593 lines

  1. "    NAME        SMACKv1.1
  2.     AUTHOR        manchester
  3.     FUNCTION    ?
  4.     ST-VERSION    2.2
  5.     PREREQUISITES    
  6.     CONFLICTS
  7.     DISTRIBUTION    world
  8.     VERSION        1
  9.     DATE    19 Aug 1988"
  10. StandardSystemController subclass: #SMACKInspectorController
  11.     instanceVariableNames: ''
  12.     classVariableNames: ''
  13.     poolDictionaries: ''
  14.     category: 'Actors-Inspectors'!
  15. SMACKInspectorController comment:
  16. 'I am a special kind of InspectorController which knows to how to remove
  17. dependents before closing.'!
  18.  
  19.  
  20. !SMACKInspectorController methodsFor: 'scheduling'!
  21.  
  22. close
  23.     "Remove the dependency between the model's object and the
  24.      model before closing."
  25.  
  26.     model object removeDependent: model.
  27.     super close! !
  28.  
  29. InspectorView subclass: #SMACKInspectorView
  30.     instanceVariableNames: ''
  31.     classVariableNames: ''
  32.     poolDictionaries: ''
  33.     category: 'Actors-Inspectors'!
  34. SMACKInspectorView comment:
  35. 'I represent a view on a special Inspector for Actor simulations.  I
  36. change my visible state when my model is updated, and can close
  37. and unschedule myself when the object being inspected is no longer
  38. required.  I also support active icons.'!
  39.  
  40.  
  41. !SMACKInspectorView methodsFor: 'updating'!
  42.  
  43. update: aParameter
  44.     "If aParameter is #all, redisplay the view.  If aParameter is
  45.     #release, remove the view. Otherwise do nothing."
  46.  
  47.     aParameter == #all ifTrue: [
  48.         ^self displaySafe: [
  49.             self isCollapsed ifFalse: [
  50.                 model changed: #field.
  51.                 model changed: #text].
  52.             self newLabel: model object labelString]].
  53.     aParameter == #release ifTrue: [controller closeAndUnschedule]! !
  54. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  55.  
  56. SMACKInspectorView class
  57.     instanceVariableNames: ''!
  58.  
  59.  
  60. !SMACKInspectorView class methodsFor: 'private'!
  61.  
  62. buildScheduledView: anInspector 
  63.     | topView |
  64.     topView _ self
  65.                 model: anInspector
  66.                 label: anInspector object labelString
  67.                 minimumSize: 180 @ 120.
  68.     topView controller: SMACKInspectorController new.
  69.     topView icon: (Icon constantNamed: #actor).
  70.     self
  71.         view: anInspector
  72.         in: (0 @ 0 extent: 1 @ 1)
  73.         of: topView.
  74.     ^topView! !
  75.  
  76. Inspector subclass: #SMACKInspector
  77.     instanceVariableNames: ''
  78.     classVariableNames: ''
  79.     poolDictionaries: ''
  80.     category: 'Actors-Inspectors'!
  81. SMACKInspector comment:
  82. 'I represent a special kind of Inspector for Actor components.  I
  83. change myself when the object inspected updates itself.'!
  84.  
  85.  
  86. !SMACKInspector methodsFor: 'updating'!
  87.  
  88. update: aParameter
  89.     "Assume everything has changed.  Update all dependents."
  90.  
  91.     self changed: aParameter! !
  92. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  93.  
  94. SMACKInspector class
  95.     instanceVariableNames: ''!
  96.  
  97.  
  98. !SMACKInspector class methodsFor: 'instance creation'!
  99.  
  100. inspect: anActor
  101.     "Answer an instance of me to provide an inspector
  102.      for anActor.  Ensure that my instance is a dependent of
  103.      anActor."
  104.  
  105.     | temp |
  106.     temp _ self new.
  107.     anActor addDependent: temp.
  108.     ^temp inspect: anActor! !
  109.  
  110. SMACKInspector subclass: #ActorDictionaryInspector
  111.     instanceVariableNames: ''
  112.     classVariableNames: 'ActorDictListMenu '
  113.     poolDictionaries: ''
  114.     category: 'Actors-Inspectors'!
  115. ActorDictionaryInspector comment:
  116. 'I am a special kind of SMACKInspector which knows how to inspect dictionaries.'!
  117.  
  118.  
  119. !ActorDictionaryInspector methodsFor: 'field list'!
  120.  
  121. acceptText: aText from: aController
  122.     | val |
  123.     field == nil ifTrue: [^ false].
  124.     val _ self evaluateText: aText string from: aController ifFail: [^ false].
  125.     object at: field put: val.
  126.     self changed: #text.
  127.     ^ true!
  128.  
  129. fieldList
  130.     "Answer a collection of the keys of the inspected dictionary."
  131.  
  132.     | keys | 
  133.     keys _ object keys.
  134.     keys detect: [:key | (key class == Symbol) not]
  135.         ifNone: [^keys asSortedCollection]. "sort dictionaries with Symbol keys"
  136.      ^keys asOrderedCollection!
  137.  
  138. fieldMenu
  139.     "ActorDictionaryInspector flushMenus" 
  140.  
  141.     field == nil ifTrue: [^ActionMenu
  142.                             labels: 'add field' withCRs
  143.                             selectors: #(addField)].
  144.     ActorDictListMenu == nil ifTrue: [
  145.         ActorDictListMenu _ ActionMenu
  146.                                 labels: 'inspect\add field\remove' withCRs
  147.                                 lines: #(1)
  148.                                 selectors: #(inspectField addField removeField)].
  149.     ^ActorDictListMenu!
  150.  
  151. fieldValue
  152.  
  153.     ^object at: field!
  154.  
  155. printItems
  156.     "Answer whether the elements of the fieldList need to be converted to strings"
  157.  
  158.     ^true! !
  159.  
  160. !ActorDictionaryInspector methodsFor: 'menu commands'!
  161.  
  162. addField
  163.     | aString key |
  164.     aString _ FillInTheBlank request: 'Enter key (an Actor identifier)'.
  165.     aString isEmpty ifFalse: [
  166.         key _ aString asSymbol.
  167.         object add: (Association key: key value: nil).
  168.         field _ key.
  169.         self changed: #field]!
  170.  
  171. removeField
  172.  
  173.     (self confirm: 'Confirm removal of ', field printString) ifTrue: [
  174.         object removeKey: field.
  175.         field _ nil.
  176.         object changed: #all.]! !
  177. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  178.  
  179. ActorDictionaryInspector class
  180.     instanceVariableNames: ''!
  181.  
  182.  
  183. !ActorDictionaryInspector class methodsFor: 'class initialization'!
  184.  
  185. flushMenus
  186.     "ActorDictionaryInspector flushMenus."
  187.  
  188.     ActorDictListMenu _ nil! !
  189.  
  190. SMACKInspector subclass: #ActorInspector
  191.     instanceVariableNames: ''
  192.     classVariableNames: 'ActorMenu '
  193.     poolDictionaries: ''
  194.     category: 'Actors-Inspectors'!
  195.  
  196.  
  197. !ActorInspector methodsFor: 'menu commands'!
  198.  
  199. openCodeView
  200.     "Open a code view on the code associated with the receiver."
  201.  
  202.     object openCodeView!
  203.  
  204. openGrapher
  205.     "Open a Grapher view on the acquaintances of the actor being
  206.      inspected."
  207.  
  208.     object graph! !
  209.  
  210. !ActorInspector methodsFor: 'field list'!
  211.  
  212. fieldMenu
  213.     "Answer with an action menu for the field view."
  214.     "ActorInspector flushMenus."
  215.  
  216.     field == nil ifTrue: [^ActionMenu
  217.                             labels: 'code\graph' withCRs
  218.                             selectors: #(openCodeView openGrapher)].
  219.     ActorMenu == nil ifTrue:
  220.         [ActorMenu _ ActionMenu
  221.                             labels: 'inspect\code\graph' withCRs
  222.                             lines: #(1)
  223.                             selectors: #(inspectField openCodeView openGrapher)].
  224.     ^ActorMenu! !
  225. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  226.  
  227. ActorInspector class
  228.     instanceVariableNames: ''!
  229.  
  230.  
  231. !ActorInspector class methodsFor: 'class initialization'!
  232.  
  233. flushMenus
  234.     "Flush the menus."
  235.     "ActorInspector flushMenus."
  236.  
  237.     ActorMenu _ nil! !
  238.  
  239. SMACKInspector subclass: #ActorCollectionInspector
  240.     instanceVariableNames: ''
  241.     classVariableNames: 'ActorCollectionMenu '
  242.     poolDictionaries: ''
  243.     category: 'Actors-Inspectors'!
  244. ActorCollectionInspector comment:
  245. 'I am a special kind of SMACKInspector which knows how to inspect collections.'!
  246.  
  247.  
  248. !ActorCollectionInspector methodsFor: 'menu commands'!
  249.  
  250. addField
  251.  
  252.     field == nil
  253.         ifTrue: [object addLast: nil]    "nothing selected"
  254.         ifFalse: [self fieldIndex isNil
  255.                 ifTrue: [object addFirst: nil]    "self selected"
  256.                 ifFalse: [object add: nil beforeIndex: self fieldIndex]].
  257.     self changed: #field!
  258.  
  259. removeField
  260.     self fieldIndex isNil ifTrue: [^self].
  261.     object removeAtIndex: self fieldIndex.
  262.     self changed: #all! !
  263.  
  264. !ActorCollectionInspector methodsFor: 'field list'!
  265.  
  266. acceptText: aText from: aController
  267.     | val |
  268.     self fieldIndex isNil ifTrue: [^false].
  269.     val _ self evaluateText: aText string from: aController ifFail: [^false].
  270.     object at: self fieldIndex put: val.
  271.     self changed: #text.
  272.     ^true!
  273.  
  274. fieldIndex
  275.     "Answer the index of the currently selected field, or nil if no index is selected."
  276.  
  277.     field isNil ifTrue: [^nil].
  278.     field = 'self' ifTrue: [^nil].
  279.     ^Integer readFromString: field!
  280.  
  281. fieldList
  282.     "Answer a collection of strings with 'self' and the indices of the
  283.      inspected ActorCollection."
  284.  
  285.     ^(Array with: 'self'),
  286.         ((1 to: object size) collect: [:i | i printString])!
  287.  
  288. fieldMenu
  289.     "ActorCollectionInspector flushMenus" 
  290.  
  291.     self fieldIndex isNil ifTrue:
  292.         [^ActionMenu
  293.             labels: 'add'
  294.             selectors: #(addField)].
  295.     ActorCollectionMenu == nil ifTrue:
  296.         [ActorCollectionMenu _
  297.             ActionMenu
  298.                 labels: 'inspect\insert\remove' withCRs
  299.                 lines: #(1)
  300.                 selectors: #(inspectField addField removeField)].
  301.     ^ActorCollectionMenu!
  302.  
  303. fieldValue
  304.  
  305.     field = 'self' ifTrue: [^object].
  306.     ^object at: self fieldIndex! !
  307. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  308.  
  309. ActorCollectionInspector class
  310.     instanceVariableNames: ''!
  311.  
  312.  
  313. !ActorCollectionInspector class methodsFor: 'class initialization'!
  314.  
  315. flushMenus
  316.     "Flush the menus."
  317.     "ActorCollectionInspector flushMenus."
  318.  
  319.     ActorCollectionMenu _ nil! !
  320.  
  321. SMACKInspector subclass: #MailAddressInspector
  322.     instanceVariableNames: ''
  323.     classVariableNames: 'MailAddressMenu '
  324.     poolDictionaries: ''
  325.     category: 'Actors-Inspectors'!
  326. MailAddressInspector comment:
  327. 'I am a special kind of inspector for Mail addresses, which knows how
  328. to inspect the corresponding actor.'!
  329.  
  330.  
  331. !MailAddressInspector methodsFor: 'field list'!
  332.  
  333. fieldMenu
  334.     "Answer with an action menu for the field view."
  335.     "MailAddressInspector flushMenus."
  336.  
  337.     field == nil ifTrue: [^ActionMenu
  338.                             labels: 'inspect actor'
  339.                             selectors: #(inspectActor)].
  340.     MailAddressMenu == nil ifTrue:
  341.         [MailAddressMenu _ ActionMenu
  342.                             labels: 'inspect\inspect actor' withCRs
  343.                             selectors: #(inspectField inspectActor)].
  344.     ^MailAddressMenu! !
  345.  
  346. !MailAddressInspector methodsFor: 'menu commands'!
  347.  
  348. inspectActor
  349.     "Inspect the actor referred to by the object."
  350.  
  351.     object class == MailAddress ifTrue: [
  352.         (MailAddress mailer table at: object ifAbsent: [nil]) inspect]! !
  353. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  354.  
  355. MailAddressInspector class
  356.     instanceVariableNames: ''!
  357.  
  358.  
  359. !MailAddressInspector class methodsFor: 'class initialization'!
  360.  
  361. flushMenus
  362.     "Flush the menu."
  363.     "MailAddressInspector flushMenus."
  364.  
  365.     MailAddressMenu _ nil! !
  366.  
  367. SMACKInspector subclass: #MailSystemInspector
  368.     instanceVariableNames: ''
  369.     classVariableNames: 'MailSystemMenu '
  370.     poolDictionaries: ''
  371.     category: 'Actors-Inspectors'!
  372.  
  373.  
  374. !MailSystemInspector methodsFor: 'field list'!
  375.  
  376. fieldMenu
  377.     "Answer with an action menu for the field view."
  378.     "MailSystemInspector flushMenus."
  379.  
  380.     field == nil ifTrue: [^ActionMenu
  381.                             labels: 'graph'
  382.                             selectors: #(openGrapher)].
  383.     MailSystemMenu == nil ifTrue:
  384.         [MailSystemMenu _ ActionMenu
  385.                             labels: 'inspect\graph' withCRs
  386.                             selectors: #(inspectField openGrapher)].
  387.     ^MailSystemMenu! !
  388.  
  389. !MailSystemInspector methodsFor: 'menu commands'!
  390.  
  391. openGrapher
  392.     "Open a Grapher view on the object being inspected."
  393.  
  394.     object graph! !
  395. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  396.  
  397. MailSystemInspector class
  398.     instanceVariableNames: ''!
  399.  
  400.  
  401. !MailSystemInspector class methodsFor: 'class initialization'!
  402.  
  403. flushMenus
  404.     "Flush the menu."
  405.     "MailSystemInspector flushMenus."
  406.  
  407.     MailSystemMenu _ nil! !
  408.  
  409. SMACKInspector subclass: #BehaviourInspector
  410.     instanceVariableNames: ''
  411.     classVariableNames: 'BehaviourMenu '
  412.     poolDictionaries: ''
  413.     category: 'Actors-Inspectors'!
  414.  
  415.  
  416. !BehaviourInspector methodsFor: 'menu commands'!
  417.  
  418. openCodeView
  419.     "Open a code view on the code associated with the receiver"
  420.  
  421.     | string |
  422.     string _ object block sourceCode.
  423.     StringHolderView
  424.         open: (StringHolder new contents: string)
  425.         label: 'Code for ', object printString.! !
  426.  
  427. !BehaviourInspector methodsFor: 'field list'!
  428.  
  429. fieldMenu
  430.     "Answer with an action menu for the field view."
  431.     "BehaviourInspector flushMenus."
  432.  
  433.     field == nil ifTrue: [^ActionMenu
  434.                             labels: 'code'
  435.                             selectors: #(openCodeView)].
  436.     BehaviourMenu == nil ifTrue:
  437.         [BehaviourMenu _ ActionMenu
  438.                             labels: 'inspect\code' withCRs
  439.                             selectors: #(inspectField openCodeView)].
  440.     ^BehaviourMenu! !
  441. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  442.  
  443. BehaviourInspector class
  444.     instanceVariableNames: ''!
  445.  
  446.  
  447. !BehaviourInspector class methodsFor: 'class initialization'!
  448.  
  449. flushMenus
  450.     "Flush the menus."
  451.     "BehaviourInspector flushMenus."
  452.  
  453.     BehaviourMenu _ nil! !
  454.  
  455. MouseMenuController subclass: #ActorInterpreterController
  456.     instanceVariableNames: ''
  457.     classVariableNames: 'ActorYellowButtonMenu ActorYellowButtonMessages '
  458.     poolDictionaries: ''
  459.     category: 'Actors-Interpreter'!
  460. ActorInterpreterController comment:
  461. 'I represent a controller for a actor interpreter.  I support a yellow button
  462. menu allowing the mode to be changed, and my model to be inspected in
  463. various ways.'!
  464.  
  465.  
  466. !ActorInterpreterController methodsFor: 'initialize-release'!
  467.  
  468. initialize
  469.     "Set up the yellow button menu."
  470.  
  471.     super initialize.
  472.     self yellowButtonMenu: ActorYellowButtonMenu 
  473.         yellowButtonMessages: ActorYellowButtonMessages! !
  474.  
  475. !ActorInterpreterController methodsFor: 'control defaults'!
  476.  
  477. controlActivity
  478.     "If the keyboard is pressed, then hand control to the corresponding
  479.      subview.  Then, cause the model to execute one interpreter cycle,
  480.      then continue as defined in the superclass."
  481.  
  482.     sensor keyboardPressed ifTrue: [self processKey].
  483.     model runProcess.
  484.     super controlActivity!
  485.  
  486. isControlActive
  487.     "Answer true if the keyboard is pressed, or if control is active
  488.      as defined in the superclass, and the blue button is not pressed.
  489.      Otherwise, answer false."
  490.  
  491.     ^sensor keyboardPressed |
  492.         super isControlActive & sensor blueButtonPressed not!
  493.  
  494. isControlWanted
  495.     "Answer true if the cursor is inside the inset display box 
  496.      of the receiver's view, or if the keyboard is pressed,
  497.      and answer false, otherwise."
  498.  
  499.     ^sensor keyboardPressed | self viewHasCursor!
  500.  
  501. processKey
  502.     "The user typed a key on the keyboard.  Give control to the subView that
  503.     is selected by this key."
  504.  
  505.     | aView |
  506.     aView _ view subViewContainingCharacter: sensor keyboard.
  507.     aView notNil ifTrue: [aView controller sendMessage]! !
  508.  
  509. !ActorInterpreterController methodsFor: 'menu messages'!
  510.  
  511. auto
  512.     "Set auto mode.  The model (interpreter) runs when the `run' button
  513.      is pressed, regardless of whether control is over the view.  The interpreter stops
  514.      when the queue becomes empty."
  515.  
  516.     self model stopWhenEmpty: false.
  517.     self model auto: true.
  518.     self model changed: #mode!
  519.  
  520. graphAll
  521.     "Open a grapher on all active actors."
  522.  
  523.     | array graph |
  524.     array _ self model activeList asArray.
  525.     (array size > 0) ifTrue: [
  526.         graph _ GraphHolder
  527.                     createForestWithRoots: array
  528.                     children: #children
  529.                     label: #graphLabel.
  530.         graph layout: #( #horizontal).
  531.         model addDependent: graph.
  532.         GraphHolderView open: graph
  533.                 label: 'Active Actors'
  534.                 menu: (ActionMenu
  535.                     labels: 'graph\code\actor\mail address\mail queue\aquaintances\behaviour\code' withCRs
  536.                     lines: #(2)
  537.                     selectors: #(graph openCodeView inspect inspectMailAddress inspectMailQueue inspectAquaintances inspectBehaviour))]
  538.         ifFalse: [self view flash]!
  539.  
  540. inspectFirst
  541.     "Inspect the first actor on the active list, if any."
  542.  
  543.     model activeList isEmpty
  544.         ifTrue: [view flash]
  545.         ifFalse: [model activeList first inspect]!
  546.  
  547. inspectModel
  548.     "Open an Inspector on the model (so that individual actors
  549.      can be inspected)."
  550.  
  551.     self model inspect!
  552.  
  553. manual
  554.     "Set manual mode.  The model (interpreter) runs when the `run' button
  555.      is pressed, and control is over the view.  The interpreter stops when
  556.      the queue becomes empty."
  557.  
  558.     self model stopWhenEmpty: true.
  559.     self model auto: false.
  560.     self model changed: #mode!
  561.  
  562. normal
  563.     "Set normal mode.  The model (interpreter) runs when the `run' button
  564.      is pressed, and control is over the view.  The interpreter remains runnable
  565.      when the queue becomes empty."
  566.  
  567.     self model stopWhenEmpty: false.
  568.     self model auto: false.
  569.     self model changed: #mode!
  570.  
  571. setHalt
  572.     "Set the model to halt."
  573.  
  574.     self model stopProcessing.
  575.     self model changed: #stopped!
  576.  
  577. setRun
  578.     "Set the model to run."
  579.  
  580.     self model startProcessing.
  581.     self model changed: #run!
  582.  
  583. stepOne
  584.     "Get the model to process one actor."
  585.  
  586.     self model processOneActor! !
  587. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  588.  
  589. ActorInterpreterController class
  590.     instanceVariableNames: ''!
  591.  
  592.  
  593. !ActorInterpreterController class methodsFor: 'class initialization'!
  594.  
  595. initialize
  596.     "Initialize the menu class variables."
  597.     "ActorInterpreterController initialize."
  598.  
  599.     ActorYellowButtonMenu _ PopUpMenu
  600.         labels: 'step\halt\run\auto\normal\manual\inspect\inspect first\graph' withCRs
  601.         lines: #(3 6 8).
  602.     ActorYellowButtonMessages _ #(stepOne setHalt setRun auto normal manual inspectModel inspectFirst graphAll).! !
  603.  
  604. ActorInterpreterController initialize!
  605.  
  606.  
  607. Model subclass: #ActorInterpreter
  608.     instanceVariableNames: 'activeActor activeList running auto stopWhenEmpty processing '
  609.     classVariableNames: ''
  610.     poolDictionaries: ''
  611.     category: 'Actors-Interpreter'!
  612. ActorInterpreter comment:
  613. 'I represent an interpreter for actors.  I maintain a list of active
  614. actors, which I process when sent the `runProcess'' message
  615. (usually from a controller).  My instance variables:
  616.  
  617. activeActor    <Actor> which is currently processing a message, or (nil).
  618.  
  619. activeList    <ActorCollection> of active actors; i.e. actors which
  620.             have one or more Tasks on their mail queues.
  621.  
  622. running        <Boolean> if true, execute the next active actor when send the
  623.             runProcess message.  Otherwise, do nothing.
  624.  
  625. auto        <Boolean> if true, will interpret actors from the activeList even
  626.             when my controller (if any) does not have control.
  627.  
  628. processing    <Boolean> if true, I am currently running in `auto'' mode.  Continue
  629.             to process further actors until the activeList is empty.
  630.  
  631. stopWhenEmpty        <Boolean> if true, reset the running flag when the active
  632.             list becomes empty.
  633.  
  634. The `auto'' and `stopWhenEmpty'' flags are interpreted to give the "mode" of
  635. the instance:
  636.  
  637. auto    stopWhenEmpty        mode
  638. ----------------------------
  639. false        false            normal
  640. false        true            manual
  641. true        false            auto
  642. true        true            *invalid*
  643. '!
  644.  
  645.  
  646. !ActorInterpreter methodsFor: 'initialize-release'!
  647.  
  648. initialize
  649.     "Initialize the instance variables."
  650.  
  651.     activeList _ ActorCollection new.
  652.     running _ true.
  653.     stopWhenEmpty _ false.
  654.     auto _ true.
  655.     processing _ false!
  656.  
  657. release
  658.     "Release any views, or other dependents."
  659.  
  660.     activeActor release.
  661.     activeList release.
  662.     self changed: #release.
  663.     super release! !
  664.  
  665. !ActorInterpreter methodsFor: 'accessing'!
  666.  
  667. activeList
  668.     "Answer with the list of active actors which I am processing."
  669.  
  670.     ^activeList!
  671.  
  672. auto
  673.     "Answer with the state of the auto flag."
  674.  
  675.     ^auto!
  676.  
  677. auto: bool
  678.     "Set the state of the auto flag to bool."
  679.  
  680.     auto _ bool!
  681.  
  682. includes: anActor
  683.     "Answer true if the receiver already refers to anActor, otherwise false."
  684.  
  685.     ^activeList includes: anActor!
  686.  
  687. running
  688.     "Answer whether the receiver is runnable."
  689.  
  690.     ^running!
  691.  
  692. size
  693.     "Answer with the number of active actors on my list."
  694.  
  695.     ^activeList size!
  696.  
  697. stopWhenEmpty
  698.     "Answer with the state of the stopWhenEmpty flag."
  699.  
  700.     ^stopWhenEmpty!
  701.  
  702. stopWhenEmpty: bool
  703.     "Set the state of the stopWhenEmpty flag to bool."
  704.  
  705.     stopWhenEmpty _ bool! !
  706.  
  707. !ActorInterpreter methodsFor: 'adding'!
  708.  
  709. addActor: anActor
  710.     "Add anActor as one to be executed by the receiver."
  711.  
  712.     (anActor == activeActor) ifFalse: [
  713.         activeList addLast: anActor.
  714.         self changed: activeList asArray.
  715.         self changed: #activeActors.
  716.         (auto & running & processing not) ifTrue: [
  717.             processing _ true.
  718.             self processAllActors]]! !
  719.  
  720. !ActorInterpreter methodsFor: 'removing'!
  721.  
  722. removeActor: anActor
  723.     "Remove anActor from the list known about by the receiver."
  724.  
  725.     activeList remove: anActor ifAbsent: [^self].
  726.     self changed: activeList asArray.
  727.     self changed: #activeActor! !
  728.  
  729. !ActorInterpreter methodsFor: 'processing'!
  730.  
  731. processActor
  732.     "Process a single task from the first actor on the receiver's list.
  733.      Insert the actor at the end of the active list if it has further
  734.      items on its mail queue."
  735.  
  736.     | currentTask |
  737.     activeActor _ activeList removeFirst.
  738.     currentTask _ activeActor getMessage.
  739.     currentTask isNil ifFalse: [
  740.         currentTask target == activeActor mailAddress ifFalse: [
  741.                         self error: 'actor has received task not addressed to it'].
  742.         activeActor behaviour block
  743.             value: activeActor
  744.             value: activeActor aquaintances
  745.             value: currentTask communication.
  746.                 currentTask release].
  747.     activeActor moreMessages
  748.         ifTrue: [activeList addLast: activeActor]
  749.         ifFalse: [
  750.             self changed: activeList asArray.
  751.             self changed: #activeActor].
  752.     activeActor _ nil!
  753.  
  754. processAllActors
  755.     "Process the entire active list."
  756.  
  757.     [processing & running] whileTrue: [self processOneActor]!
  758.  
  759. processOneActor
  760.     "Process the first Task on the mail queue of the first actor in the 
  761.      receiver's active list, if any.  Insert the actor at the end of the 
  762.      active list if it has further items on its mail queue."
  763.  
  764.     activeList isEmpty
  765.         ifTrue: [
  766.             processing _ false.
  767.             stopWhenEmpty ifTrue: [
  768.                 running _ false.
  769.                 self changed: #stopped]]
  770.         ifFalse: [self processActor]!
  771.  
  772. runProcess
  773.     "If the receiver is running, process the next actor from the
  774.      process list."
  775.  
  776.     running ifTrue: [self processOneActor]!
  777.  
  778. startProcessing
  779.     "Start the receiver processing further actors."
  780.  
  781.     running _ true!
  782.  
  783. stopProcessing
  784.     "Stop the receiver from processing further actors."
  785.  
  786.     running _ false! !
  787. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  788.  
  789. ActorInterpreter class
  790.     instanceVariableNames: ''!
  791.  
  792.  
  793. !ActorInterpreter class methodsFor: 'instance creation'!
  794.  
  795. new
  796.     "Answer with a new initialized instance of the receiver."
  797.  
  798.     ^super new initialize! !
  799.  
  800. View subclass: #ActorInterpreterView
  801.     instanceVariableNames: 'stopButton goButton '
  802.     classVariableNames: ''
  803.     poolDictionaries: ''
  804.     category: 'Actors-Interpreter'!
  805. ActorInterpreterView comment:
  806. 'I represent a view on an interpreter for actors.'!
  807.  
  808.  
  809. !ActorInterpreterView methodsFor: 'subView access'!
  810.  
  811. subViewContainingCharacter: aCharacter
  812.     "Answer the receiver's subView that corresponds to the key, aCharacter.
  813.     Answer nil if no subView is selected by aCharacter."
  814.  
  815.     self subViews reverseDo: 
  816.         [:aSubView |
  817.         (aSubView containsKey: aCharacter) ifTrue: [^aSubView]].
  818.     ^nil! !
  819.  
  820. !ActorInterpreterView methodsFor: 'updating'!
  821.  
  822. update: aParameter
  823.     "If aParameter is #stopped, then toggle the halt button.  If
  824.      aParameter is #run, then toggle the run button.  If aParameter
  825.      is #release, then close the view."
  826.  
  827.     aParameter == #stopped ifTrue: [stopButton turnOn].
  828.     aParameter == #run ifTrue: [goButton turnOn].
  829.     aParameter == #release ifTrue: [self topView controller closeAndUnschedule]! !
  830.  
  831. !ActorInterpreterView methodsFor: 'private'!
  832.  
  833. insertButtonViews
  834.     "Set up the button views for a new instance of the receiver."
  835.  
  836.     | stepView stopView runView connector |
  837.     stepView _ SwitchView new model: (
  838.         Button newOff onAction: [self model processOneActor]).
  839.     stepView label: ('step' asDisplayText).
  840.     stepView controller: IndicatorOnSwitchController new.
  841.     stepView borderWidth: 2.
  842.     stepView key: $s.
  843.     self addSubView: stepView viewport: (20@100 extent: 40@28).
  844.  
  845.     connector _ Object new.        "Dummy object for connections."
  846.     self model running
  847.         ifTrue: [stopButton _ OneOnSwitch newOff]
  848.         ifFalse: [stopButton _ OneOnSwitch newOn].
  849.     stopButton onAction: [self model stopProcessing].
  850.     stopButton connection: connector.
  851.     stopView _ SwitchView new model: stopButton.
  852.     stopView label: ('halt' asDisplayText).
  853.     stopView borderWidth: 2.
  854.     stopView key: $h.
  855.     self addSubView: stopView viewport: (80@100 extent: 40@28).
  856.  
  857.     self model running
  858.         ifTrue: [goButton _ OneOnSwitch newOn]
  859.         ifFalse: [goButton _ OneOnSwitch newOff].
  860.     goButton onAction: [self model startProcessing].
  861.     goButton connection: connector.
  862.     runView _ SwitchView new model: goButton.
  863.     runView label: ('run' asDisplayText).
  864.     runView borderWidth: 2.
  865.     runView key: $r.
  866.     self addSubView: runView viewport: (140@100 extent: 40@28).!
  867.  
  868. insertDisplayViews
  869.     "Set up the display views for a new instance of the receiver."
  870.  
  871.     | actorView modeView |
  872.     modeView _ ActorInterpreterModeView new.
  873.     modeView controller: NoController new.
  874.     modeView model: self model.
  875.     modeView insideColor: Form white.
  876.     modeView borderWidth: 2.
  877.     self addSubView: modeView viewport: (20 @ 12 extent: 160 @ 32).
  878.  
  879.     actorView _ ActorInterpreterDisplayView new.
  880.     actorView model: self model.
  881.     actorView insideColor: Form white.
  882.     actorView controller: NoController new.
  883.     actorView borderWidth: 2.
  884.     self addSubView: actorView viewport: (20 @ 50 extent: 160 @ 32)! !
  885. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  886.  
  887. ActorInterpreterView class
  888.     instanceVariableNames: ''!
  889.  
  890.  
  891. !ActorInterpreterView class methodsFor: 'instance creation'!
  892.  
  893. open
  894.     "Create and schedule a view on the current Actor interpreter."
  895.     "ActorInterpreterView open."
  896.  
  897.     self openOn: Actor interpreter!
  898.  
  899. openOn: anActorInterpreter
  900.     "Create and schedule a view on anActorInterpreter."
  901.     "ActorInterpreterView openOn: Actor interpreter."
  902.  
  903.     | topView view |
  904.     topView _ StandardSystemView
  905.                 model: nil
  906.                 label: 'Actor Interpreter'
  907.                 minimumSize: 200@150.
  908.     topView insideColor: nil.
  909.  
  910.     view _ self new.
  911.     view controller: ActorInterpreterController new.
  912.     view model: anActorInterpreter.
  913.     view insideColor: Form gray.
  914.     view borderColor: Form black.
  915.     view borderWidth: 1.
  916.     topView
  917.         addSubView: view
  918.         window: (0@0 extent: 200@150)
  919.         viewport: topView window.
  920.  
  921.     view insertButtonViews.
  922.     view insertDisplayViews.
  923.  
  924.     topView controller open! !
  925.  
  926. View subclass: #ActorInterpreterDisplayView
  927.     instanceVariableNames: 'displayedValue '
  928.     classVariableNames: ''
  929.     poolDictionaries: ''
  930.     category: 'Actors-Interpreter'!
  931. ActorInterpreterDisplayView comment:
  932. 'I represent a display of the number of active actors in the model.'!
  933.  
  934.  
  935. !ActorInterpreterDisplayView methodsFor: 'displaying'!
  936.  
  937. displayView
  938.     "Display the number of actors on the model's list."
  939.  
  940.     displayedValue _ model size.
  941.     ((displayedValue = 1)
  942.         ifTrue: ['1 actor active']
  943.         ifFalse: [self model size printString, ' actors active'])
  944.             displayAt: (self insetDisplayBox topLeft + (10@6)).! !
  945.  
  946. !ActorInterpreterDisplayView methodsFor: 'updating'!
  947.  
  948. update: parameter
  949.     "If the parameter is #activeActors, update the displayed
  950.      value, provided that my topView is not collapsed."
  951.  
  952.     (displayedValue isNil or: [displayedValue ~= model size]) ifTrue: [
  953.         self topView isCollapsed ifFalse: [
  954.             self displaySafe: [self display]]]! !
  955.  
  956. !ActorInterpreterDisplayView methodsFor: 'subView access'!
  957.  
  958. containsKey: aCharacter
  959.     "This view does not respond to any characters."
  960.  
  961.     ^false! !
  962.  
  963. View subclass: #ActorInterpreterModeView
  964.     instanceVariableNames: ''
  965.     classVariableNames: ''
  966.     poolDictionaries: ''
  967.     category: 'Actors-Interpreter'!
  968. ActorInterpreterModeView comment:
  969. 'I represent a display of the mode of the model.'!
  970.  
  971.  
  972. !ActorInterpreterModeView methodsFor: 'displaying'!
  973.  
  974. displayView
  975.     "Display the current mode."
  976.  
  977.     | stop |
  978.     stop _ self model stopWhenEmpty.
  979.     (Text
  980.         string: (self model auto
  981.             ifTrue: [stop ifTrue: ['Unknown mode'] ifFalse: ['Auto mode']]
  982.             ifFalse: [stop ifTrue: ['Manual mode'] ifFalse: ['Normal mode']])
  983.         emphasis: 2) asDisplayText displayAt: (self insetDisplayBox topLeft + (10@6))! !
  984.  
  985. !ActorInterpreterModeView methodsFor: 'subView access'!
  986.  
  987. containsKey: aCharacter
  988.     "This view does not respond to any characters."
  989.  
  990.     ^false! !
  991.  
  992. !ActorInterpreterModeView methodsFor: 'updating'!
  993.  
  994. update: aParameter
  995.     "If parameter is #mode, update the receiver's display.  Otherwise,
  996.      do nothing."
  997.  
  998.     aParameter == #mode ifTrue: [    self display]! !
  999.  
  1000. Dictionary variableSubclass: #ActorDictionary
  1001.     instanceVariableNames: ''
  1002.     classVariableNames: ''
  1003.     poolDictionaries: ''
  1004.     category: 'Actors-Simulation'!
  1005. ActorDictionary comment:
  1006. 'I am a subclass of Dictionary which knows about active inspectors.'!
  1007.  
  1008.  
  1009. !ActorDictionary methodsFor: 'initialize-release'!
  1010.  
  1011. release
  1012.     "Release any views on me."
  1013.  
  1014.     self associationsDo: [:eachAssociation |
  1015.         eachAssociation key release.
  1016.         eachAssociation value release].
  1017.     self changed: #release.
  1018.     super release! !
  1019.  
  1020. !ActorDictionary methodsFor: 'accessing'!
  1021.  
  1022. at: key put: value
  1023.     "Override the method in the superclass in order to signal changes."
  1024.  
  1025.     | temp |
  1026.     temp _ super at: key put: value.
  1027.     self changed: #all.
  1028.     ^temp! !
  1029.  
  1030. !ActorDictionary methodsFor: 'dictionary removing'!
  1031.  
  1032. removeKey: key ifAbsent: aBlock
  1033.     "Override the method in the superclass in order to signal changes."
  1034.  
  1035.     | temp |
  1036.     temp _ super removeKey: key ifAbsent: aBlock.
  1037.     self changed: #all.
  1038.     ^temp! !
  1039.  
  1040. !ActorDictionary methodsFor: 'inspecting'!
  1041.  
  1042. inspect
  1043.     "Use special dictionary inspector for actor simulations."
  1044.  
  1045.     SMACKInspectorView open: (ActorDictionaryInspector inspect: self)!
  1046.  
  1047. labelString
  1048.     "Answer with a string suitable for use as a view's label."
  1049.  
  1050.     ^self class name! !
  1051.  
  1052. OrderedCollection variableSubclass: #ActorCollection
  1053.     instanceVariableNames: ''
  1054.     classVariableNames: ''
  1055.     poolDictionaries: ''
  1056.     category: 'Actors-Simulation'!
  1057. ActorCollection comment:
  1058. 'I am a subclass of OrderedCollection which knows about
  1059. interactive inspectors.'!
  1060.  
  1061.  
  1062. !ActorCollection methodsFor: 'initialize-release'!
  1063.  
  1064. release
  1065.     "Release any views on me."
  1066.  
  1067.     self do: [:each | each release].
  1068.     self changed: #release.
  1069.     super release! !
  1070.  
  1071. !ActorCollection methodsFor: 'accessing'!
  1072.  
  1073. at: anInteger put: anObject
  1074.     "Override the method in the superclass in order to indicate changes."
  1075.  
  1076.     | temp |
  1077.     temp _ super at: anInteger put: anObject.
  1078.     self changed: #all.
  1079.     ^temp! !
  1080.  
  1081. !ActorCollection methodsFor: 'adding'!
  1082.  
  1083. addLast: newObject
  1084.     "Override the method in the sueprclass in order to signal changes."
  1085.  
  1086.     | temp |
  1087.     temp _ super addLast: newObject.
  1088.     self changed: #all.
  1089.     ^temp! !
  1090.  
  1091. !ActorCollection methodsFor: 'removing'!
  1092.  
  1093. remove: oldObject ifAbsent: aBlock
  1094.     "Override the method in the superclass in order to signal changes."
  1095.  
  1096.     | temp |
  1097.     temp _ super remove: oldObject ifAbsent: aBlock.
  1098.     self changed: #all.
  1099.     ^temp!
  1100.  
  1101. removeFirst
  1102.     "Override the method in the superclass in order to signal changes."
  1103.  
  1104.     | temp |
  1105.     temp _ super removeFirst.
  1106.     self changed: #all.
  1107.     ^temp!
  1108.  
  1109. removeLast
  1110.     "Override the method in the superclass in order to signal changes."
  1111.  
  1112.     | temp |
  1113.     temp _ super removeLast.
  1114.     self changed: #all.
  1115.     ^temp! !
  1116.  
  1117. !ActorCollection methodsFor: 'inspecting'!
  1118.  
  1119. inspect
  1120.     "Use special inspector for actor simulations."
  1121.  
  1122.     SMACKInspectorView open: (ActorCollectionInspector inspect: self)!
  1123.  
  1124. labelString
  1125.     "Answer with a string suitable for use as a view's label."
  1126.  
  1127.     ^self class name! !
  1128.  
  1129. !ActorCollection methodsFor: 'private'!
  1130.  
  1131. insert: anObject before: spot
  1132.     "Override the method in the superclass in order to signal changes."
  1133.  
  1134.     | temp |
  1135.     temp _ super insert: anObject before: spot.
  1136.     self changed: #all.
  1137.     ^temp! !
  1138.  
  1139. Model subclass: #ActorModel
  1140.     instanceVariableNames: ''
  1141.     classVariableNames: ''
  1142.     poolDictionaries: ''
  1143.     category: 'Actors-Simulation'!
  1144. ActorModel comment:
  1145. 'I represent the abstract superclass of `dynamic'' actor entities; i.e. those
  1146. which are created and destroyed as the system runs.'!
  1147.  
  1148.  
  1149. !ActorModel methodsFor: 'initialize-release'!
  1150.  
  1151. release
  1152.     "Remove any views on me.  Subclasses should include 'super release'
  1153.      in any re-implementations."
  1154.  
  1155.     self changed: #release.
  1156.     super release! !
  1157.  
  1158. !ActorModel methodsFor: 'inspecting'!
  1159.  
  1160. inspect
  1161.     "Use special inspector for actor simulations."
  1162.  
  1163.     SMACKInspectorView open: (SMACKInspector inspect: self)!
  1164.  
  1165. labelString
  1166.     "Answer with a string suitable for use as a view's label."
  1167.  
  1168.     ^self printString! !
  1169.  
  1170. ActorModel subclass: #MailSystem
  1171.     instanceVariableNames: 'table '
  1172.     classVariableNames: ''
  1173.     poolDictionaries: ''
  1174.     category: 'Actors-Simulation'!
  1175. MailSystem comment:
  1176. 'I represent a mail system capable of routing messages (Tasks) from one
  1177. actor to another.
  1178.  
  1179. My instance variables are:
  1180.  
  1181. table        <ActorDictionary> with <key> being a <MailAddress>, and <value>
  1182.             being a <Actor>.'!
  1183.  
  1184.  
  1185. !MailSystem methodsFor: 'initialize-release'!
  1186.  
  1187. initialize
  1188.     "Initialize the address table."
  1189.  
  1190.     table _ ActorDictionary new!
  1191.  
  1192. release
  1193.     "Release my instance variables."
  1194.  
  1195.     table release.
  1196.     super release! !
  1197.  
  1198. !MailSystem methodsFor: 'accessing'!
  1199.  
  1200. table
  1201.     "Answer with the table of addresses.  Only used by the inspector."
  1202.  
  1203.     ^table! !
  1204.  
  1205. !MailSystem methodsFor: 'adding'!
  1206.  
  1207. addAddress: mailAddress to: actor
  1208.     "Insert the mail address mailAddress to the Actor actor in the
  1209.     routing table.  Answer with the actor inserted."
  1210.  
  1211.     table at: mailAddress put: actor.
  1212.     self changed: #all.
  1213.     self changed: (Array with: self).
  1214.     ^actor! !
  1215.  
  1216. !MailSystem methodsFor: 'removing'!
  1217.  
  1218. removeAddress: mailAddr
  1219.     "Remove knowledge of the mail address mailAddr, and the associated
  1220.      actor, from the routing table. Answer with the actor associated with
  1221.      mailAddr.  Create a error message if the mailAddr is unknown."
  1222.  
  1223.     | temp |
  1224.     temp _ table
  1225.         removeKey: mailAddr
  1226.         ifAbsent: ["self error:
  1227.             'Trying to remove a non-existent mail address'." ^nil].
  1228.     self changed: #all.
  1229.     self changed: (Array with: self).
  1230.     ^temp value! !
  1231.  
  1232. !MailSystem methodsFor: 'sending'!
  1233.  
  1234. send: aTask to: aMailAddress
  1235.     "Send aTask to the actor with address
  1236.      aMailAddress."
  1237.  
  1238.     (table at: aMailAddress
  1239.         ifAbsent: [^self error: 'Trying to send to non-existent mail address'])
  1240.             addMessage: aTask! !
  1241.  
  1242. !MailSystem methodsFor: 'printing'!
  1243.  
  1244. printOn: aStream
  1245.     "Put a printable representation of the receiver on aStream."
  1246.  
  1247.     aStream nextPutAll: self class name.
  1248.     aStream nextPutAll: ' ('.
  1249.     table size printOn: aStream.
  1250.     aStream nextPut: $)! !
  1251.  
  1252. !MailSystem methodsFor: 'grapher access'!
  1253.  
  1254. children
  1255.     "Answer with a Set of actors regarded as my children for display
  1256.     purposes."
  1257.  
  1258.     ^table values asSet!
  1259.  
  1260. graph
  1261.     "Open a Grapher view on all actors known about by the receiver."
  1262.  
  1263.     | graph |
  1264.     graph _ GraphHolder
  1265.                 createForestWithRoots: (Array with: self)
  1266.                     children: #children
  1267.                     label: #graphLabel.
  1268.     graph layout: #( #horizontal).
  1269.     self addDependent: graph.
  1270.     GraphHolderView open: graph
  1271.                 label: 'Graph of ', self class name
  1272.                 menu: (ActionMenu
  1273.                     labels: 'graph\code\actor\mail address\mail queue\aquaintances\behaviour\code' withCRs
  1274.                     lines: #(2)
  1275.                     selectors: #(graph openCodeView inspect inspectMailAddress inspectMailQueue inspectAquaintances inspectBehaviour))!
  1276.  
  1277. graphLabel
  1278.     "Answer with a Text being the lable used by Grapher."
  1279.  
  1280.     ^self class name asText allBold, (' (', table size printString, ')') asText! !
  1281.  
  1282. !MailSystem methodsFor: 'inspecting'!
  1283.  
  1284. inspect
  1285.     "Use special inspector for the Mail system."
  1286.  
  1287.     SMACKInspectorView open: (MailSystemInspector inspect: self)!
  1288.  
  1289. inspectAquaintances
  1290.     "Do nothing.  For compatibility with class Actor."!
  1291.  
  1292. inspectBehaviour
  1293.     "Do nothing.  For compatibility with class Actor."!
  1294.  
  1295. inspectMailAddress
  1296.     "Do nothing.  For compatibility with class Actor."!
  1297.  
  1298. inspectMailQueue
  1299.     "Do nothing.  For compatibility with class Actor."!
  1300.  
  1301. openCodeView
  1302.     "Do nothing.  For compatibility with class Actor."! !
  1303.  
  1304. !MailSystem methodsFor: 'garbage collection'!
  1305.  
  1306. garbageCollect
  1307.     "Remove unwanted actors from the mail system."
  1308.     "MailAddress mailer garbageCollect."
  1309.  
  1310.     | g1 g2 actor size |
  1311.     g1 _ Smalltalk select: [:g | g class == MailAddress].
  1312.     g2 _ ActorDictionary new.
  1313.     g1 associationsDo: [:eachAssociation |
  1314.         g2
  1315.             at: (Smalltalk at: eachAssociation key)
  1316.             put: (self removeAddress: eachAssociation value)].
  1317.     size _ table size.
  1318.     self release.
  1319.  
  1320.     self initialize.
  1321.     Smalltalk garbageCollect.
  1322.     Transcript show: 'Collected ', size printString, ' actors'; cr.
  1323.     g2 associationsDo: [:e | self addAddress: e key to: e value]! !
  1324. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1325.  
  1326. MailSystem class
  1327.     instanceVariableNames: ''!
  1328.  
  1329.  
  1330. !MailSystem class methodsFor: 'instance creation'!
  1331.  
  1332. new
  1333.     "Create a new initialized instance of the receiver."
  1334.  
  1335.     ^super new initialize! !
  1336.  
  1337. ActorModel subclass: #MailAddress
  1338.     instanceVariableNames: ''
  1339.     classVariableNames: 'Mailer '
  1340.     poolDictionaries: ''
  1341.     category: 'Actors-Simulation'!
  1342. MailAddress comment:
  1343. 'I represent a unique mail address to which messages may be
  1344. sent.  Messages are routed by an instance of <MailSystem>,
  1345. referred to by my class variable `Mailer''.  Mail addresses do not
  1346. change.'!
  1347.  
  1348.  
  1349. !MailAddress methodsFor: 'initialize-release'!
  1350.  
  1351. release
  1352.     "Remove my actor from the mail system."
  1353.  
  1354.     self removeAddress.
  1355.     super release! !
  1356.  
  1357. !MailAddress methodsFor: 'adding'!
  1358.  
  1359. addAddressTo: actor
  1360.     "Add the receiver as a mail address to the Actor actor, in the mail system."
  1361.  
  1362.     Mailer addAddress: self to: actor! !
  1363.  
  1364. !MailAddress methodsFor: 'removing'!
  1365.  
  1366. removeAddress
  1367.     "Remove the receiver as a mail address known about by the
  1368.      mail system.  Answer with the actor previously known about."
  1369.  
  1370.     ^Mailer removeAddress: self! !
  1371.  
  1372. !MailAddress methodsFor: 'sending'!
  1373.  
  1374. send: aTask
  1375.     "Send aTask to the actor with mail address represented by
  1376.      the receiver."
  1377.  
  1378.     Mailer send: aTask to: self!
  1379.  
  1380. sendCommunication: aCommunication
  1381.     "Create a task with aCommunication, and send it to the actor
  1382.      represented by the receiver."
  1383.  
  1384.     (Task communication: aCommunication target: self) send!
  1385.  
  1386. sendMessage: aSymbol
  1387.     "Create a task with a communication with name aSymbol and no
  1388.      arguments, and send it to the actor represented by the receiver."
  1389.  
  1390.     self sendCommunication: (Communication name: aSymbol)!
  1391.  
  1392. sendMessage: aSymbol with: firstArgument
  1393.     "Create a task with a communication with name aSymbol and one
  1394.      argument, and send it to the actor represented by the receiver."
  1395.  
  1396.     self sendCommunication: (Communication name: aSymbol with: firstArgument)!
  1397.  
  1398. sendMessage: aSymbol with: firstArgument with: secondArgument
  1399.     "Create a task with a communication with name aSymbol and two
  1400.      arguments, and send it to the actor represented by the receiver."
  1401.  
  1402.     self sendCommunication: (
  1403.         Communication
  1404.             name: aSymbol
  1405.             with: firstArgument
  1406.             with: secondArgument)!
  1407.  
  1408. sendMessage: aSymbol with: firstArgument with: secondArgument with: thirdArgument
  1409.     "Create a task with a communication with name aSymbol and three
  1410.      arguments, and send it to the actor represented by the receiver."
  1411.  
  1412.     self sendCommunication: (
  1413.         Communication
  1414.             name: aSymbol
  1415.             with: firstArgument
  1416.             with: secondArgument
  1417.             with: thirdArgument)!
  1418.  
  1419. sendMessage: aSymbol withArguments: anArray
  1420.     "Create a task with a communication with name aSymbol and
  1421.      arguments from anArray, and send it to the actor represented
  1422.      by the receiver."
  1423.  
  1424.     self sendCommunication: (Communication name: aSymbol withArguments: anArray)! !
  1425.  
  1426. !MailAddress methodsFor: 'printing'!
  1427.  
  1428. labelString
  1429.     "Answer with a string suitable for use as a label."
  1430.  
  1431.     ^self class name, ' (', self printString, ')'!
  1432.  
  1433. printOn: aStream
  1434.     "Put a printable representation of the receiver on aStream."
  1435.  
  1436.     aStream nextPutAll: self asOop printString! !
  1437.  
  1438. !MailAddress methodsFor: 'inspecting'!
  1439.  
  1440. inspect
  1441.     "Use special inspector for mail addresses."
  1442.  
  1443.     SMACKInspectorView open: (MailAddressInspector inspect: self)! !
  1444. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1445.  
  1446. MailAddress class
  1447.     instanceVariableNames: ''!
  1448.  
  1449.  
  1450. !MailAddress class methodsFor: 'class initialization'!
  1451.  
  1452. initialize
  1453.     "Initialize my class variable, which represents a mail system
  1454.      capable of routing messages between actors."
  1455.     "MailAddress initialize."
  1456.  
  1457.     Mailer notNil ifTrue: [Mailer release].
  1458.     Mailer _ MailSystem new! !
  1459.  
  1460. !MailAddress class methodsFor: 'class access'!
  1461.  
  1462. mailer
  1463.     "Answer with the current instance of MailSystem being used by
  1464.      the receiver."
  1465.  
  1466.     ^Mailer! !
  1467.  
  1468. MailAddress initialize!
  1469.  
  1470.  
  1471. ActorModel subclass: #Aquaintances
  1472.     instanceVariableNames: 'contents '
  1473.     classVariableNames: ''
  1474.     poolDictionaries: ''
  1475.     category: 'Actors-Simulation'!
  1476. Aquaintances comment:
  1477. 'I represent a list of aquaintances.  My instance variable is:
  1478.  
  1479. contents    <Dictionary> with <key> being a <Symbol> (my name for
  1480.             the aquaintance), and <value> being a <MailAddress> for
  1481.             the aquaintance.
  1482. '!
  1483.  
  1484.  
  1485. !Aquaintances methodsFor: 'initialize-release'!
  1486.  
  1487. initialize
  1488.     "Initialize the instance variable."
  1489.  
  1490.     contents _ ActorDictionary new.!
  1491.  
  1492. release
  1493.     "Release all my instance variables."
  1494.  
  1495.     contents release.
  1496.     super release! !
  1497.  
  1498. !Aquaintances methodsFor: 'accessing'!
  1499.  
  1500. contents
  1501.     "Answer with the entire aquaintance dictionary."
  1502.  
  1503.     ^contents!
  1504.  
  1505. name: aSymbol
  1506.     "Answer with the mail address of an actor known by the receiver
  1507.      as aSymbol.  Create an error message if aSymbol is not found."
  1508.  
  1509.     ^contents
  1510.         at: aSymbol
  1511.         ifAbsent: [self error: 'Attempted to access an aquaintance which is unknown']!
  1512.  
  1513. name: aSymbol mailAddress: aMailAddress
  1514.     "Insert the aquaintance known as aSymbol with address aMailAddress."
  1515.  
  1516.     contents at: aSymbol put: aMailAddress.
  1517.     self changed: #all! !
  1518.  
  1519. !Aquaintances methodsFor: 'sending'!
  1520.  
  1521. name: aName sendCommunication: aCommunication
  1522.     "Send a Task containing aCommunication to the mailAddress
  1523.      accessed by aName."
  1524.  
  1525.     (self name: aName) sendCommunication: aCommunication!
  1526.  
  1527. name: aName sendMessage: aSymbol
  1528.     "Send a message called aSymbol to the mailAddress
  1529.      accessed by aName."
  1530.  
  1531.     (self name: aName) sendMessage: aSymbol!
  1532.  
  1533. name: aName sendMessage: aSymbol with: firstArgument
  1534.     "Send a message called aSymbol with one argument to the mailAddress
  1535.      accessed by aName."
  1536.  
  1537.     (self name: aName) sendMessage: aSymbol with: firstArgument!
  1538.  
  1539. name: aName sendMessage: aSymbol with: firstArgument with: secondArgument
  1540.     "Send a message called aSymbol with two arguments to the mailAddress
  1541.      accessed by aName."
  1542.  
  1543.     (self name: aName)
  1544.         sendMessage: aSymbol
  1545.         with: firstArgument
  1546.         with: secondArgument!
  1547.  
  1548. name: aName sendMessage: aSymbol with: firstArgument with: secondArgument with: thirdArgument
  1549.     "Send a message called aSymbol with three arguments to the mailAddress
  1550.      accessed by aName."
  1551.  
  1552.     (self name: aName)
  1553.         sendMessage: aSymbol
  1554.         with: firstArgument
  1555.         with: secondArgument
  1556.         with: thirdArgument!
  1557.  
  1558. name: aName sendMessage: aSymbol withArguments: anArray
  1559.     "Send a message called aSymbol with arguments from anArray
  1560.      to the mailAddress accessed by aName."
  1561.  
  1562.     (self name: aName) sendMessage: aSymbol withArguments: anArray! !
  1563.  
  1564. !Aquaintances methodsFor: 'printing'!
  1565.  
  1566. printOn: aStream
  1567.     "Put a printable representation of the receiver on aStream."
  1568.  
  1569.     self class name printOn: aStream.
  1570.     aStream nextPutAll: ' (', contents size printString, ')'! !
  1571. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1572.  
  1573. Aquaintances class
  1574.     instanceVariableNames: ''!
  1575.  
  1576.  
  1577. !Aquaintances class methodsFor: 'instance creation'!
  1578.  
  1579. name: aSymbol mailAddress: aMailAddress
  1580.     "Answer with an instance of the receiver which knows about
  1581.      aSymbol referring to aMailAddress."
  1582.  
  1583.     ^self new name: aSymbol mailAddress: aMailAddress!
  1584.  
  1585. name: s1 mailAddress: m1 name: s2 mailAddress: m2
  1586.     "Answer with an instance of the receiver which knows about
  1587.      s1 referring to m1, and s2 referring to m3."
  1588.  
  1589.     ^(self new name: s1 mailAddress: m1) name: s2 mailAddress: m2!
  1590.  
  1591. new
  1592.     "Answer with a new initialized instance of the receiver."
  1593.  
  1594.     ^super new initialize! !
  1595.  
  1596. ActorModel subclass: #Actor
  1597.     instanceVariableNames: 'mailAddress behaviour mailQueue aquaintances '
  1598.     classVariableNames: 'Interpreter '
  1599.     poolDictionaries: ''
  1600.     category: 'Actors-Simulation'!
  1601. Actor comment:
  1602. 'I represent a potentially concurrent object.
  1603.  
  1604. My instance variables are:
  1605.  
  1606. behaviour        <Behaviour> describing my actions when a message is
  1607.                 received.
  1608.  
  1609. mailAddress        <MailAddress> representing the unique identity of an
  1610.                 instance of me.
  1611.  
  1612. mailQueue        <MailQueue> representing messages to be processed.
  1613.  
  1614. aquaintances    <Aquaintances> representing my names for other actors
  1615.                 instances of me know about.
  1616.  
  1617.  
  1618. My class variable "Interpreter" is an instance of <ActorInterpreter> which
  1619. represents the execution engine for instances of this class.'!
  1620.  
  1621.  
  1622. !Actor methodsFor: 'initialize-release'!
  1623.  
  1624. destroy
  1625.     "Nil out and release appropriate instance variables, so that the
  1626.      receiver can be garbage-collected."
  1627.  
  1628.     mailAddress release.
  1629.     mailAddress _ nil.
  1630.     behaviour changed: #release.
  1631.     mailQueue changed: #release.
  1632.     aquaintances changed: #release.
  1633.     aquaintances _ nil.
  1634.     self changed: #release!
  1635.  
  1636. initialize
  1637.     "Initialize the mail address, mail queue and aquaintances instance
  1638.      variables."
  1639.  
  1640.     mailAddress _ MailAddress new.
  1641.     mailAddress addAddressTo: self.
  1642.     mailQueue _ MailQueue new.
  1643.     aquaintances _ Aquaintances new.!
  1644.  
  1645. release
  1646.     "Nil out the receiver's mail address, to break up possible cycles.
  1647.      Remove the receiver from the list maintained by the interpreter.
  1648.      Release all the receiver's instance variables."
  1649.  
  1650.     mailAddress _ nil.
  1651.     mailQueue release.
  1652.     behaviour release.
  1653.     aquaintances release.
  1654.     Interpreter removeActor: self.
  1655.     super release! !
  1656.  
  1657. !Actor methodsFor: 'accessing'!
  1658.  
  1659. aquaintances
  1660.     "Answer with the aquaintances of the receiver.  Only used by the interpreter."
  1661.  
  1662.     ^aquaintances!
  1663.  
  1664. behaviour
  1665.     "Answer with the behaviour of the receiver.  Only used by the interpreter."
  1666.  
  1667.     ^behaviour!
  1668.  
  1669. mailAddress
  1670.     "Answer with the mail address of the receiver."
  1671.  
  1672.     ^mailAddress! !
  1673.  
  1674. !Actor methodsFor: 'messages'!
  1675.  
  1676. addMessage: aMessage
  1677.     "Add aMessage to the receiver's queue of messages."
  1678.  
  1679.     | test |
  1680.     test _ mailQueue isEmpty.
  1681.     mailQueue addMessage: aMessage.
  1682.     test ifTrue: [Interpreter addActor: self].
  1683.     self changed: #all!
  1684.  
  1685. getMessage
  1686.     "Answer with the first message from the mail queue.  Only used by
  1687.      the interpreter."
  1688.  
  1689.     | task |
  1690.     task _ mailQueue getMessage.
  1691.     self changed: #all.
  1692.     ^task!
  1693.  
  1694. moreMessages
  1695.     "Answer true if there are further messages to process, otherwise
  1696.      false."
  1697.  
  1698.     ^mailQueue isEmpty not! !
  1699.  
  1700. !Actor methodsFor: 'behaviour'!
  1701.  
  1702. becomes: aBehaviour
  1703.     "The behaviour of the receiver becomes aBehaviour.  The
  1704.      aquaintances are unchanged."
  1705.  
  1706.     behaviour _ aBehaviour.
  1707.     self changed: #all!
  1708.  
  1709. becomes: aBehaviour withAquaintances: anAquaintances
  1710.     "The behaviour of the receiver becomes aBehaviour, with
  1711.      aquaintances anAquaintances."
  1712.  
  1713.     behaviour _ aBehaviour.
  1714.     aquaintances _ anAquaintances.
  1715.     self changed: (Array with: self).
  1716.     self changed: #all! !
  1717.  
  1718. !Actor methodsFor: 'printing'!
  1719.  
  1720. printOn: aStream
  1721.     "Put a printable representation of the receiver on aStream."
  1722.  
  1723.     aStream nextPutAll: self class name.
  1724.     aStream nextPutAll: ' ('.
  1725.     mailAddress printOn: aStream.
  1726.     aStream nextPut: $)! !
  1727.  
  1728. !Actor methodsFor: 'inspecting'!
  1729.  
  1730. inspect
  1731.     "Use special inspector for actors."
  1732.  
  1733.     SMACKInspectorView open: (ActorInspector inspect: self)!
  1734.  
  1735. inspectAquaintances
  1736.     "Open an inspector on the receiver's aquaintances."
  1737.  
  1738.     aquaintances inspect!
  1739.  
  1740. inspectBehaviour
  1741.     "Open an inspector on the receiver's behaviour."
  1742.  
  1743.     behaviour inspect!
  1744.  
  1745. inspectMailAddress
  1746.     "Open an inspector on the receiver's mail address."
  1747.  
  1748.     mailAddress inspect!
  1749.  
  1750. inspectMailQueue
  1751.     "Open an inspector on the receiver's mail queue."
  1752.  
  1753.     mailQueue inspect!
  1754.  
  1755. openCodeView
  1756.     "Open a code view on the code associated with the receiver"
  1757.  
  1758.     | string |
  1759.     string _ behaviour block sourceCode.
  1760.     StringHolderView
  1761.         open: (StringHolder new contents: string)
  1762.         label: 'Code for ', self printString.! !
  1763.  
  1764. !Actor methodsFor: 'grapher access'!
  1765.  
  1766. children
  1767.     "Answer with a set of actors regarded as my children for display
  1768.      purposes."
  1769.  
  1770.     | newSet |
  1771.     newSet _ Set new.
  1772.     aquaintances isNil ifFalse: [
  1773.         aquaintances contents values asSet do: [ :eachMailAddress |
  1774.             eachMailAddress class == MailAddress ifTrue: [
  1775.                 newSet add: (MailAddress mailer table at: eachMailAddress)]]].
  1776.     ^newSet!
  1777.  
  1778. graph
  1779.     "Open a grapher on the receiver and its aquaintances."
  1780.  
  1781.     | graph |
  1782.     graph _ GraphHolder
  1783.                 createForestWithRoots: (Array with: self)
  1784.                     children: #children
  1785.                     label: #graphLabel.
  1786.     graph layout: #( #horizontal).
  1787.     self addDependent: graph.
  1788.     GraphHolderView open: graph
  1789.                 label: 'Graph of ', self labelString
  1790.                 menu: (ActionMenu
  1791.                     labels: 'graph\code\actor\mail address\mail queue\aquaintances\behaviour\code' withCRs
  1792.                     lines: #(2)
  1793.                     selectors: #(graph openCodeView inspect inspectMailAddress inspectMailQueue inspectAquaintances inspectBehaviour))!
  1794.  
  1795. graphLabel
  1796.     "Answer with a Text being the label used by grapher."
  1797.  
  1798.     | selector |
  1799.     behaviour isNil
  1800.         ifTrue: [selector _ #none]
  1801.         ifFalse: [
  1802.             selector _ (behaviour block receiver class)
  1803.                 selectorAtMethod: (behaviour block method)
  1804.                 setClass: [:d | ]].
  1805.     ^self class name asText allBold,
  1806.         (' (', mailAddress printString, ')\[', selector printString, ']') withCRs asText! !
  1807.  
  1808. !Actor methodsFor: 'private'!
  1809.  
  1810. setAquaintances: anAquaintances
  1811.     "Set the aquaintances of the receiver to anAquaintances."
  1812.  
  1813.     aquaintances _ anAquaintances! !
  1814. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1815.  
  1816. Actor class
  1817.     instanceVariableNames: ''!
  1818.  
  1819.  
  1820. !Actor class methodsFor: 'instance creation'!
  1821.  
  1822. new
  1823.     "Answer with a new initialized instance of the receiver."
  1824.  
  1825.     ^super new initialize!
  1826.  
  1827. withAquaintances: anAquaintances
  1828.     "Create a new instance of the receiver, with aquaintances
  1829.      defined by anAquaintances.  Answer with the mail address of
  1830.      the new instance."
  1831.  
  1832.     ^(self new setAquaintances: anAquaintances) mailAddress!
  1833.  
  1834. withAquaintances: anAquaintances withBehaviour: aBehaviour
  1835.     "Create a new instance of the receiver, with aquaintances
  1836.      defined by anAquaintances, and behaviour defined by aBehaviour.
  1837.      Answer with the mail address of the new instance."
  1838.  
  1839.     | temp |
  1840.     temp _ self new setAquaintances: anAquaintances.
  1841.     temp becomes: aBehaviour.
  1842.     ^temp mailAddress!
  1843.  
  1844. withBehaviour: aBehaviour
  1845.     "Create a new instance of the receiver, with behaviour
  1846.      defined by aBehaviour.  Answer with the mail address of the new
  1847.      instance."
  1848.  
  1849.     ^(self new becomes: aBehaviour) mailAddress!
  1850.  
  1851. withBehaviour: aBehaviour withAquaintances: anAquaintances
  1852.     "Create a new instance of the receiver, with aquaintances
  1853.      defined by anAquaintances, and behaviour defined by aBehaviour.
  1854.      Answer with the mail address of the new instance."
  1855.  
  1856.     | temp |
  1857.     temp _ self new setAquaintances: anAquaintances.
  1858.     temp becomes: aBehaviour.
  1859.     ^temp mailAddress! !
  1860.  
  1861. !Actor class methodsFor: 'class initialization'!
  1862.  
  1863. initialize
  1864.     "Initialize the class variable Interpreter, which represents the
  1865.      execution enginer for instances of the receiver."
  1866.     "Actor initialize."
  1867.  
  1868.     Interpreter notNil ifTrue: [Interpreter release].
  1869.     Interpreter _ ActorInterpreter new.! !
  1870.  
  1871. !Actor class methodsFor: 'class access'!
  1872.  
  1873. interpreter
  1874.     "Answer with the current instance of ActorInterpreter in use by
  1875.      the receiver."
  1876.      "Actor interpreter basicInspect"
  1877.  
  1878.     ^Interpreter! !
  1879.  
  1880. !Actor class methodsFor: 'examples'!
  1881.  
  1882. exampleWorkspace1
  1883.     "Select and execute the expressions here to play with actors."
  1884.  
  1885.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1886.     ActorTextCollector newTranscript.        "Create a new actor transcript."
  1887.     ActorTextCollector open.        "Open a view on the actor transcript."
  1888.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1889.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1890.  
  1891.     ActorTranscript sendMessage: #clear.
  1892.     ActorTranscript sendMessage: #show with: 'Hello, world!!'.!
  1893.  
  1894. exampleWorkspace10
  1895.     "Select and execute the expressions here to run a timed fibonacci example."
  1896.  
  1897.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1898.     ActorTextCollector open.        "Open a view on the actor transcript."
  1899.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1900.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1901.  
  1902.     "This bit creates a global actor capable of timing."
  1903.  
  1904.     Smalltalk at: #ActorTimer put: (Actor withBehaviour: Behaviour timer).
  1905.  
  1906.     "This bit finds the time taken for 'null' activity."
  1907.     "
  1908.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  1909.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1910.         (com name == #start) ifTrue: [
  1911.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1912.             slf becomes: secondBehaviour]].
  1913.  
  1914.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1915.         (com name == #reply) ifTrue: [
  1916.  
  1917.             slf mailAddress sendMessage: #reply with: 1.
  1918.  
  1919.             slf
  1920.                 becomes: thirdBehaviour
  1921.                 withAquaintances: (Aquaintances
  1922.                     name: #startTime mailAddress: (com at: 1))]].
  1923.  
  1924.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1925.         (com name == #reply) ifTrue: [
  1926.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1927.             slf becomes: fourthBehaviour]].
  1928.  
  1929.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1930.         (com name == #reply) ifTrue: [
  1931.             ActorTranscript sendMessage: #cr.
  1932.             ActorTranscript
  1933.                 sendMessage: #show
  1934.                 with: 'Time taken for no activity was: '.
  1935.             ActorTranscript sendMessage: #show with:
  1936.                 ((com at: 1) - (acq name: #startTime)) printString.
  1937.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1938.  
  1939.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1940.     "
  1941.     "This bit actually runs the fibonacci example."
  1942.     "
  1943.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  1944.  
  1945.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  1946.         (com name == #start) ifTrue: [
  1947.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1948.             slf becomes: secondBehaviour]].
  1949.  
  1950.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  1951.         (com name == #reply) ifTrue: [
  1952.             (Actor
  1953.                 withBehaviour: Behaviour fibonacci
  1954.                 withAquaintances: (Aquaintances
  1955.                     name: #replyTo
  1956.                     mailAddress: slf mailAddress))
  1957.                 sendMessage: #fibonacci with: 13.
  1958.             slf
  1959.                 becomes: thirdBehaviour
  1960.                 withAquaintances: (Aquaintances
  1961.                     name: #startTime mailAddress: (com at: 1))]].
  1962.  
  1963.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  1964.         (com name == #reply) ifTrue: [
  1965.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  1966.             slf becomes: fourthBehaviour]].
  1967.  
  1968.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  1969.         (com name == #reply) ifTrue: [
  1970.             ActorTranscript sendMessage: #cr.
  1971.             ActorTranscript
  1972.                 sendMessage: #show
  1973.                 with: 'Time taken for fibonacci (13) was: '.
  1974.             ActorTranscript sendMessage: #show with:
  1975.                 ((com at: 1) - (acq name: #startTime)) printString.
  1976.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  1977.  
  1978.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  1979.     "!
  1980.  
  1981. exampleWorkspace11
  1982.     "Select and execute the expressions here to run an iterative factorial example."
  1983.  
  1984.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  1985.     ActorTextCollector open.        "Open a view on the actor transcript."
  1986.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  1987.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  1988.  
  1989.     "
  1990.     | startBehaviour iterateBehaviour |
  1991.  
  1992.     startBehaviour _ Behaviour block: [:slf :acq :com |
  1993.         (com name == #factorial) ifTrue: [
  1994.             slf
  1995.                 becomes: iterateBehaviour
  1996.                 withAquaintances: (Aquaintances
  1997.                     name: #current mailAddress: 1
  1998.                     name: #replyTo mailAddress: (acq name: #replyTo)).
  1999.             slf mailAddress sendMessage: #iterate with: (com at: 1)]].
  2000.  
  2001.     iterateBehaviour _ Behaviour block: [:slf :acq :com |
  2002.         (com name == #iterate)
  2003.             ifTrue: [
  2004.                 ((com at: 1) <= 1)
  2005.                     ifTrue: [
  2006.                         slf becomes: startBehaviour    .
  2007.                         (acq name: #replyTo)
  2008.                             sendMessage: #reply with: (acq name: #current)]
  2009.                     ifFalse: [
  2010.                         acq name: #current mailAddress: (acq name: #current) * (com at: 1).
  2011.                         slf mailAddress sendMessage: #iterate with: ((com at: 1) - 1)]]].
  2012.  
  2013.     (Actor
  2014.         withBehaviour: startBehaviour
  2015.         withAquaintances: (Aquaintances
  2016.             name: #replyTo mailAddress: (Actor
  2017.                 withBehaviour: (Behaviour displaySink)))) sendMessage: #factorial with: 20.
  2018.  
  2019.     "!
  2020.  
  2021. exampleWorkspace12
  2022.     "Select and execute the expressions here to run a timed iterative
  2023.      factorial example."
  2024.  
  2025.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2026.     ActorTextCollector open.        "Open a view on the actor transcript."
  2027.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2028.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2029.  
  2030.     "This bit creates a global actor capable of timing."
  2031.  
  2032.     Smalltalk at: #ActorTimer put: (Actor withBehaviour: Behaviour timer).
  2033.  
  2034.     "This bit finds the time taken for 'null' activity."
  2035.     "
  2036.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  2037.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  2038.         (com name == #start) ifTrue: [
  2039.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2040.             slf becomes: secondBehaviour]].
  2041.  
  2042.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  2043.         (com name == #reply) ifTrue: [
  2044.  
  2045.             slf mailAddress sendMessage: #reply with: 1.
  2046.  
  2047.             slf
  2048.                 becomes: thirdBehaviour
  2049.                 withAquaintances: (Aquaintances
  2050.                     name: #startTime mailAddress: (com at: 1))]].
  2051.  
  2052.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  2053.         (com name == #reply) ifTrue: [
  2054.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2055.             slf becomes: fourthBehaviour]].
  2056.  
  2057.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  2058.         (com name == #reply) ifTrue: [
  2059.             ActorTranscript sendMessage: #cr.
  2060.             ActorTranscript
  2061.                 sendMessage: #show
  2062.                 with: 'Time taken for no activity was: '.
  2063.             ActorTranscript sendMessage: #show with:
  2064.                 ((com at: 1) - (acq name: #startTime)) printString.
  2065.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  2066.  
  2067.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  2068.     "
  2069.     "This bit actually runs the iterative factorial example."
  2070.     "
  2071.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour
  2072.       startBehaviour iterateBehaviour |
  2073.  
  2074.     startBehaviour _ Behaviour block: [:slf :acq :com |
  2075.         (com name == #factorial) ifTrue: [
  2076.             slf
  2077.                 becomes: iterateBehaviour
  2078.                 withAquaintances: (Aquaintances
  2079.                     name: #current mailAddress: 1
  2080.                     name: #replyTo mailAddress: (acq name: #replyTo)).
  2081.             slf mailAddress sendMessage: #iterate with: (com at: 1)]].
  2082.  
  2083.  
  2084.     iterateBehaviour _ Behaviour block: [:slf :acq :com |
  2085.         (com name == #iterate)
  2086.             ifTrue: [
  2087.                 ((com at: 1) <= 1)
  2088.                     ifTrue: [
  2089.                         slf becomes: startBehaviour    .
  2090.                         (acq name: #replyTo)
  2091.                             sendMessage: #reply with: (acq name: #current)]
  2092.                     ifFalse: [
  2093.                         slf
  2094.                             becomes: iterateBehaviour
  2095.                             withAquaintances: (Aquaintances
  2096.                                 name: #current
  2097.                                 mailAddress: ((acq name: #current) * (com at: 1))
  2098.                                 name: #replyTo
  2099.                                 mailAddress: (acq name: #replyTo)).
  2100.                         slf mailAddress sendMessage: #iterate with: ((com at: 1) - 1)]]].
  2101.  
  2102.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  2103.         (com name == #start) ifTrue: [
  2104.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2105.             slf becomes: secondBehaviour]].
  2106.  
  2107.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  2108.         (com name == #reply) ifTrue: [
  2109.             (Actor
  2110.                 withBehaviour: startBehaviour
  2111.                 withAquaintances: (Aquaintances
  2112.                     name: #replyTo
  2113.                     mailAddress: slf mailAddress))
  2114.                 sendMessage: #factorial with: 20.
  2115.             slf
  2116.                 becomes: thirdBehaviour
  2117.                 withAquaintances: (Aquaintances
  2118.                     name: #startTime mailAddress: (com at: 1))]].
  2119.  
  2120.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  2121.         (com name == #reply) ifTrue: [
  2122.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2123.             slf becomes: fourthBehaviour]].
  2124.  
  2125.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  2126.         (com name == #reply) ifTrue: [
  2127.             ActorTranscript sendMessage: #cr.
  2128.             ActorTranscript
  2129.                 sendMessage: #show
  2130.                 with: 'Time taken for factorial (20) was: '.
  2131.             ActorTranscript sendMessage: #show with:
  2132.                 ((com at: 1) - (acq name: #startTime)) printString.
  2133.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  2134.  
  2135.  
  2136.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  2137.  
  2138.     "!
  2139.  
  2140. exampleWorkspace13
  2141.     "Select and execute the expressions here to run a divide-and-conquor
  2142.      factorial example."
  2143.  
  2144.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2145.     ActorTextCollector open.        "Open a view on the actor transcript."
  2146.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2147.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2148.  
  2149.     (Actor
  2150.         withBehaviour: Behaviour rangeProduct
  2151.         withAquaintances: (Aquaintances
  2152.             name: #replyTo
  2153.             mailAddress: (Actor withBehaviour: (Behaviour displaySink))))
  2154.                 sendMessage: #factorial with: 1 with: 20!
  2155.  
  2156. exampleWorkspace14
  2157.     "Select and execute the expressions here to run a timed version of the
  2158.      divide-and-conquor factorial example.  This is based on the code on page 45
  2159.      of 'Object Oriented Concurrent Programming'."
  2160.  
  2161.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2162.     ActorTextCollector open.        "Open a view on the actor transcript."
  2163.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2164.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2165.  
  2166.     "This bit creates a global actor capable of timing."
  2167.  
  2168.     Smalltalk at: #ActorTimer put: (Actor withBehaviour: Behaviour timer).
  2169.  
  2170.     "This bit finds the time taken for 'null' activity."
  2171.     "
  2172.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  2173.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  2174.         (com name == #start) ifTrue: [
  2175.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2176.             slf becomes: secondBehaviour]].
  2177.  
  2178.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  2179.         (com name == #reply) ifTrue: [
  2180.  
  2181.             slf mailAddress sendMessage: #reply with: 1.
  2182.  
  2183.             slf
  2184.                 becomes: thirdBehaviour
  2185.                 withAquaintances: (Aquaintances
  2186.                     name: #startTime mailAddress: (com at: 1))]].
  2187.  
  2188.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  2189.         (com name == #reply) ifTrue: [
  2190.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2191.             slf becomes: fourthBehaviour]].
  2192.  
  2193.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  2194.         (com name == #reply) ifTrue: [
  2195.             ActorTranscript sendMessage: #cr.
  2196.             ActorTranscript
  2197.                 sendMessage: #show
  2198.                 with: 'Time taken for no activity was: '.
  2199.             ActorTranscript sendMessage: #show with:
  2200.                 ((com at: 1) - (acq name: #startTime)) printString.
  2201.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  2202.  
  2203.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  2204.     "
  2205.     "This bit actually runs the factorial."
  2206.     "
  2207.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  2208.  
  2209.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  2210.         (com name == #start) ifTrue: [
  2211.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2212.             slf becomes: secondBehaviour]].
  2213.  
  2214.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  2215.         (com name == #reply) ifTrue: [
  2216.             (Actor
  2217.                 withBehaviour: Behaviour rangeProduct
  2218.                 withAquaintances: (Aquaintances
  2219.                     name: #replyTo
  2220.                     mailAddress: slf mailAddress))
  2221.                 sendMessage: #factorial with: 1 with: 20.
  2222.             slf
  2223.                 becomes: thirdBehaviour
  2224.                 withAquaintances: (Aquaintances
  2225.                     name: #startTime mailAddress: (com at: 1))]].
  2226.  
  2227.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  2228.         (com name == #reply) ifTrue: [
  2229.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2230.             slf becomes: fourthBehaviour]].
  2231.  
  2232.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  2233.         (com name == #reply) ifTrue: [
  2234.             ActorTranscript sendMessage: #cr.
  2235.             ActorTranscript
  2236.                 sendMessage: #show
  2237.                 with: 'Time taken for factorial (20) was: '.
  2238.             ActorTranscript sendMessage: #show with:
  2239.                 ((com at: 1) - (acq name: #startTime)) printString.
  2240.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  2241.  
  2242.  
  2243.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  2244.  
  2245.     "!
  2246.  
  2247. exampleWorkspace15
  2248.     "Select and execute the expressions here to run a takeuchi example."
  2249.  
  2250.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2251.     ActorTextCollector open.        "Open a view on the actor transcript."
  2252.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2253.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2254.  
  2255.     (Actor withBehaviour: Behaviour takeuchi
  2256.         withAquaintances: (Aquaintances
  2257.             name: #replyTo
  2258.             mailAddress: (Actor withBehaviour: Behaviour displaySink)))
  2259.                 sendMessage: #tak with: 4 with: 3 with: 1!
  2260.  
  2261. exampleWorkspace16
  2262.     "Select and execute the expressions here to run a timed takeuchi example.
  2263.      WARNING: running tak(18,12,6) takes a long time (hours!!)."
  2264.  
  2265.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2266.     ActorTextCollector open.        "Open a view on the actor transcript."
  2267.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2268.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2269.  
  2270.     "This bit creates a global actor capable of timing."
  2271.  
  2272.     Smalltalk at: #ActorTimer put: (Actor withBehaviour: Behaviour timer).
  2273.  
  2274.     "This bit finds the time taken for 'null' activity."
  2275.     "
  2276.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  2277.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  2278.         (com name == #start) ifTrue: [
  2279.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2280.             slf becomes: secondBehaviour]].
  2281.  
  2282.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  2283.         (com name == #reply) ifTrue: [
  2284.  
  2285.             slf mailAddress sendMessage: #reply with: 1.
  2286.  
  2287.             slf
  2288.                 becomes: thirdBehaviour
  2289.                 withAquaintances: (Aquaintances
  2290.                     name: #startTime mailAddress: (com at: 1))]].
  2291.  
  2292.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  2293.         (com name == #reply) ifTrue: [
  2294.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2295.             slf becomes: fourthBehaviour]].
  2296.  
  2297.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  2298.         (com name == #reply) ifTrue: [
  2299.             ActorTranscript sendMessage: #cr.
  2300.             ActorTranscript
  2301.                 sendMessage: #show
  2302.                 with: 'Time taken for no activity was: '.
  2303.             ActorTranscript sendMessage: #show with:
  2304.                 ((com at: 1) - (acq name: #startTime)) printString.
  2305.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  2306.  
  2307.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  2308.     "
  2309.  
  2310.     "This bit actually finds the time taken to run the takeuchi function."
  2311.     "
  2312.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  2313.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  2314.         (com name == #start) ifTrue: [
  2315.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2316.             slf becomes: secondBehaviour]].
  2317.  
  2318.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  2319.         (com name == #reply) ifTrue: [
  2320.             (Actor withBehaviour: Behaviour takeuchi
  2321.                 withAquaintances: (Aquaintances
  2322.                     name: #replyTo
  2323.                     mailAddress: slf mailAddress))
  2324.                         sendMessage: #tak with: 18 with: 12 with: 6.
  2325.             slf
  2326.                 becomes: thirdBehaviour
  2327.                 withAquaintances: (Aquaintances
  2328.                     name: #startTime mailAddress: (com at: 1))]].
  2329.  
  2330.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  2331.         (com name == #reply) ifTrue: [
  2332.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2333.             slf becomes: fourthBehaviour]].
  2334.  
  2335.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  2336.         (com name == #reply) ifTrue: [
  2337.             ActorTranscript sendMessage: #cr.
  2338.             ActorTranscript
  2339.                 sendMessage: #show
  2340.                 with: 'Time taken for takeuchi(18, 12, 6) was: '.
  2341.             ActorTranscript sendMessage: #show with:
  2342.                 ((com at: 1) - (acq name: #startTime)) // 1000 printString.
  2343.             ActorTranscript sendMessage: #show with: ' seconds.']].
  2344.  
  2345.     ActorTranscript sendMessage: #clear.
  2346.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  2347.     "!
  2348.  
  2349. exampleWorkspace2
  2350.     "Select and execute the expressions here to run the forwarder example."
  2351.  
  2352.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2353.     ActorTextCollector open.        "Open a view on the actor transcript."
  2354.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2355.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2356.     "
  2357.     | forwarder |
  2358.     forwarder _ Actor
  2359.         withBehaviour: (Behaviour forwarder)
  2360.         withAquaintances: (Aquaintances name: #link mailAddress: ActorTranscript).
  2361.     forwarder sendMessage: #clear.
  2362.     forwarder sendMessage: #show with: 'Hello, once again!!'.
  2363.     "!
  2364.  
  2365. exampleWorkspace3
  2366.     "Select and execute the expressions here to run the stack example."
  2367.  
  2368.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2369.     ActorTextCollector open.        "Open a view on the actor transcript."
  2370.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2371.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2372.     "
  2373.     | sink stack |
  2374.  
  2375.     sink _ Actor withBehaviour: (Behaviour stackSink).
  2376.  
  2377.     stack _ Actor withBehaviour: Behaviour stackNode withAquaintances: (
  2378.         Aquaintances
  2379.                 name: #content mailAddress: nil
  2380.                 name: #link mailAddress: nil).
  2381.  
  2382.     ActorTranscript sendMessage: #clear.
  2383.     stack
  2384.         sendMessage: #push
  2385.         with: (Actor
  2386.             withBehaviour: Behaviour stackItem
  2387.             withAquaintances: (Aquaintances name: #count mailAddress: 1)).
  2388.     stack
  2389.         sendMessage: #push
  2390.         with: (Actor
  2391.             withBehaviour: Behaviour stackItem
  2392.             withAquaintances: (Aquaintances name: #count mailAddress: 2)).
  2393.  
  2394.     stack sendMessage: #pop with: sink.
  2395.  
  2396.     stack
  2397.         sendMessage: #push
  2398.         with: (Actor
  2399.             withBehaviour: Behaviour stackItem
  2400.             withAquaintances: (Aquaintances name: #count mailAddress: 3)).
  2401.  
  2402.     stack sendMessage: #pop with: sink.
  2403.     stack sendMessage: #pop with: sink.
  2404.  
  2405.     "!
  2406.  
  2407. exampleWorkspace4
  2408.     "Select and execute the expressions here to run the simple recursive
  2409.      factorial example."
  2410.  
  2411.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2412.     ActorTextCollector open.        "Open a view on the actor transcript."
  2413.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2414.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2415.  
  2416.     (Actor withBehaviour: Behaviour factorial)
  2417.         sendMessage: #factorial with: 3 with: (
  2418.             Actor withBehaviour: (Behaviour displaySink)).!
  2419.  
  2420. exampleWorkspace5
  2421.     "Select and execute the expressions here to run another simple recursive
  2422.      factorial example."
  2423.  
  2424.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2425.     ActorTextCollector open.        "Open a view on the actor transcript."
  2426.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2427.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2428.  
  2429.     ActorTranscript sendMessage: #clear.
  2430.     ActorTranscript sendMessage: #show with: 'Factorial (20) = '.
  2431.     (Actor withBehaviour: Behaviour factorial)
  2432.         sendMessage: #factorial with: 20 with: (
  2433.             Actor withBehaviour: (Behaviour displaySink)).!
  2434.  
  2435. exampleWorkspace6
  2436.     "Select and execute the expressions here to run a timer example."
  2437.  
  2438.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2439.     ActorTextCollector open.        "Open a view on the actor transcript."
  2440.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2441.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2442.  
  2443.     "This bit creates a global actor capable of timing."
  2444.  
  2445.     Smalltalk at: #ActorTimer put: (Actor withBehaviour: Behaviour timer).
  2446.  
  2447.     "This bit prints the date and time on the Actor Transcript."
  2448.  
  2449.     ActorTimer sendMessage: #now with: (
  2450.         Actor withBehaviour: (Behaviour displaySink)).
  2451.  
  2452.     "This bit prints the date on the Actor Transcript."
  2453.  
  2454.     ActorTimer sendMessage: #date with: (
  2455.         Actor withBehaviour: (Behaviour displaySink)).
  2456.  
  2457.     "This bit prints the time on the Actor Transcript."
  2458.  
  2459.     ActorTimer sendMessage: #time with: (
  2460.         Actor withBehaviour: (Behaviour displaySink)).!
  2461.  
  2462. exampleWorkspace7
  2463.     "Select and execute the expressions here to run another timer example."
  2464.  
  2465.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2466.     ActorTextCollector open.        "Open a view on the actor transcript."
  2467.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2468.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2469.  
  2470.     "This bit creates a global actor capable of timing."
  2471.  
  2472.     Smalltalk at: #ActorTimer put: (Actor withBehaviour: Behaviour timer).
  2473.  
  2474.     "This bit displays the millisecond clock on the Actor Transcript."
  2475.  
  2476.     ActorTimer sendMessage: #milliseconds with: (
  2477.         Actor withBehaviour: (Behaviour displaySink)).!
  2478.  
  2479. exampleWorkspace8
  2480.     "Select and execute the expressions here to run a timed simple recursive
  2481.      factorial example."
  2482.  
  2483.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2484.     ActorTextCollector open.        "Open a view on the actor transcript."
  2485.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2486.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2487.  
  2488.     "This bit creates a global actor capable of timing."
  2489.  
  2490.     Smalltalk at: #ActorTimer put: (Actor withBehaviour: Behaviour timer).
  2491.  
  2492.     "This bit finds the time taken for 'null' activity."
  2493.     "
  2494.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour |
  2495.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  2496.         (com name == #start) ifTrue: [
  2497.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2498.             slf becomes: secondBehaviour]].
  2499.  
  2500.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  2501.         (com name == #reply) ifTrue: [
  2502.  
  2503.             slf mailAddress sendMessage: #reply with: 1.
  2504.  
  2505.             slf
  2506.                 becomes: thirdBehaviour
  2507.                 withAquaintances: (Aquaintances
  2508.                     name: #startTime mailAddress: (com at: 1))]].
  2509.  
  2510.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  2511.         (com name == #reply) ifTrue: [
  2512.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2513.             slf becomes: fourthBehaviour]].
  2514.  
  2515.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  2516.         (com name == #reply) ifTrue: [
  2517.             ActorTranscript sendMessage: #cr.
  2518.             ActorTranscript
  2519.                 sendMessage: #show
  2520.                 with: 'Time taken for no activity was: '.
  2521.             ActorTranscript sendMessage: #show with:
  2522.                 ((com at: 1) - (acq name: #startTime)) printString.
  2523.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  2524.  
  2525.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  2526.     "
  2527.     "This bit actually times the factorial."
  2528.     "
  2529.     | firstBehaviour secondBehaviour thirdBehaviour fourthBehaviour
  2530.       recFactorial recCustomer |
  2531.  
  2532.     firstBehaviour _ Behaviour block: [:slf :acq :com |
  2533.         (com name == #start) ifTrue: [
  2534.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2535.             slf becomes: secondBehaviour]].
  2536.  
  2537.     secondBehaviour _ Behaviour block: [:slf :acq :com |
  2538.         (com name == #reply) ifTrue: [
  2539.             (Actor withBehaviour: Behaviour factorial)
  2540.                 sendMessage: #factorial with: 20 with: slf mailAddress.
  2541.             slf
  2542.                 becomes: thirdBehaviour
  2543.                 withAquaintances: (Aquaintances
  2544.                     name: #startTime mailAddress: (com at: 1))]].
  2545.  
  2546.     thirdBehaviour _ Behaviour block: [:slf :acq :com |
  2547.         (com name == #reply) ifTrue: [
  2548.             ActorTimer sendMessage: #milliseconds with: slf mailAddress.
  2549.             slf becomes: fourthBehaviour]].
  2550.  
  2551.     fourthBehaviour _ Behaviour block: [:slf :acq :com |
  2552.         (com name == #reply) ifTrue: [
  2553.             ActorTranscript sendMessage: #cr.
  2554.             ActorTranscript
  2555.                 sendMessage: #show
  2556.                 with: 'Time taken for factorial (20) was: '.
  2557.             ActorTranscript sendMessage: #show with:
  2558.                 ((com at: 1) - (acq name: #startTime)) printString.
  2559.             ActorTranscript sendMessage: #show with: ' milliseconds.']].
  2560.  
  2561.     (Actor withBehaviour: firstBehaviour) sendMessage: #start
  2562.     "!
  2563.  
  2564. exampleWorkspace9
  2565.     "Select and execute the expressions here to run a fibonacci example."
  2566.  
  2567.     ActorInterpreterView open.        "Open a view on the actor interpreter."
  2568.     ActorTextCollector open.        "Open a view on the actor transcript."
  2569.     MailAddress mailer inspect.        "Open an inspector on the mail system."
  2570.     MailAddress mailer garbageCollect.        "Collect unwanted actors."
  2571.  
  2572.     (Actor
  2573.         withBehaviour: Behaviour fibonacci
  2574.         withAquaintances: (Aquaintances
  2575.             name: #replyTo
  2576.             mailAddress: (Actor withBehaviour: Behaviour displaySink)))
  2577.                 sendMessage: #fibonacci with: 5.! !
  2578.  
  2579. Actor initialize!
  2580.  
  2581.  
  2582. ActorModel subclass: #Behaviour
  2583.     instanceVariableNames: 'block '
  2584.     classVariableNames: ''
  2585.     poolDictionaries: ''
  2586.     category: 'Actors-Simulation'!
  2587. Behaviour comment:
  2588. 'I represent the current activity of an actor.  My instance variable:
  2589.  
  2590. block    <BlockContext> which is activated when the actor receives a
  2591.         task.  The block expects three arguments, representing `slf'' (the
  2592.         actor receiving the task), `acq'' (the aquaintances of the actor,
  2593.         and `com'' the communication in the present task.'!
  2594.  
  2595.  
  2596. !Behaviour methodsFor: 'initialize-release'!
  2597.  
  2598. release
  2599.     "Release the instance variable."
  2600.  
  2601.     block release.
  2602.     super release! !
  2603.  
  2604. !Behaviour methodsFor: 'accessing'!
  2605.  
  2606. block
  2607.     "Answer with the block describing the behaviour of the receiver."
  2608.  
  2609.     ^block!
  2610.  
  2611. block: aBlock
  2612.     "Make the activity of the receiver aBlock."
  2613.  
  2614.     block _ aBlock.
  2615.     self changed: #all! !
  2616.  
  2617. !Behaviour methodsFor: 'printing'!
  2618.  
  2619. printOn: aStream
  2620.     "Put a printable representation of the receiver on aStream."
  2621.  
  2622.     self class name printOn: aStream! !
  2623.  
  2624. !Behaviour methodsFor: 'inspecting'!
  2625.  
  2626. inspect
  2627.     "Use special inspector for behaviours."
  2628.  
  2629.     SMACKInspectorView open: (BehaviourInspector inspect: self)! !
  2630. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2631.  
  2632. Behaviour class
  2633.     instanceVariableNames: ''!
  2634.  
  2635.  
  2636. !Behaviour class methodsFor: 'instance creation'!
  2637.  
  2638. block: aBlock
  2639.     "Create a new instance of the receiver, with activity called aSymbol
  2640.      as described by aBlock."
  2641.  
  2642.     ^self new block: aBlock! !
  2643.  
  2644. !Behaviour class methodsFor: 'standard behaviours'!
  2645.  
  2646. displaySink
  2647.     "Answer with a Behaviour which absorbs any incoming communications,
  2648.      and displays their values in the Actor Transcript."
  2649.  
  2650.     ^Behaviour block: [ :slf :acq :com |
  2651.         ActorTranscript sendMessage: #clear.
  2652.         com arguments do: [ :eachArgument |
  2653.             ActorTranscript sendMessage: #show with: eachArgument printString.
  2654.             ActorTranscript sendMessage: #cr]]!
  2655.  
  2656. factorial
  2657.     "Answer with a Behaviour which performs a recursive factorial."
  2658.  
  2659.     ^Behaviour block: [:slf :acq :com |
  2660.         (com name == #factorial) ifTrue: [
  2661.             (com at: 1) = 0
  2662.                 ifTrue: [
  2663.                     (com at: 2) sendMessage: #reply with: 1.
  2664.                     slf destroy]
  2665.                 ifFalse: [
  2666.                     slf mailAddress
  2667.                         sendMessage: #factorial
  2668.                         with: ((com at: 1) - 1)
  2669.                         with: (Actor
  2670.                             withBehaviour: Behaviour factorialCustomer
  2671.                             withAquaintances: (Aquaintances
  2672.                                 name: #n mailAddress: (com at: 1)
  2673.                                 name: #replyTo mailAddress: (com at: 2)))]]]!
  2674.  
  2675. factorialCustomer
  2676.     "Answer with a Behaviour which acts as a customer for the
  2677.      recursive factorial implementation."
  2678.  
  2679.     ^Behaviour block: [:slf :acq :com |
  2680.         (com name == #reply) ifTrue: [
  2681.             (acq name: #replyTo)
  2682.                 sendMessage: #reply
  2683.                 with: ((acq name: #n) * (com at: 1)).
  2684.             slf destroy]]!
  2685.  
  2686. fibonacci
  2687.     "Answer with a Behaviour which performs fibonacci calculations."
  2688.  
  2689.     | fibonacciBehaviour |
  2690.     fibonacciBehaviour _ Behaviour block: [:slf :acq :com |
  2691.         (com name == #fibonacci) ifTrue: [
  2692.             ((com at: 1) <= 1)
  2693.                 ifTrue: [
  2694.                     (acq name: #replyTo) sendMessage: #reply with: (com at: 1).
  2695.                     slf destroy]
  2696.                 ifFalse: [
  2697.                     slf becomes: Behaviour fibonacciWaitBoth.
  2698.                     (Actor
  2699.                         withBehaviour: fibonacciBehaviour
  2700.                         withAquaintances: (Aquaintances
  2701.                             name: #replyTo
  2702.                             mailAddress: slf mailAddress))
  2703.                                 sendMessage: #fibonacci
  2704.                                 with: ((com at: 1) - 1).
  2705.                     (Actor
  2706.                         withBehaviour: fibonacciBehaviour
  2707.                         withAquaintances: (Aquaintances
  2708.                             name: #replyTo
  2709.                             mailAddress: slf mailAddress))
  2710.                                 sendMessage: #fibonacci
  2711.                                 with: ((com at: 1) - 2)]]].
  2712.     ^fibonacciBehaviour!
  2713.  
  2714. fibonacciWaitBoth
  2715.     "Answer with a Behaviour which wait for both parts of a
  2716.      fibonacci calculation."
  2717.  
  2718.     ^Behaviour block: [:slf :acq :com |
  2719.         (com name == #reply) ifTrue: [
  2720.             slf
  2721.                 becomes: Behaviour fibonacciWaitOne
  2722.                 withAquaintances: (Aquaintances
  2723.                     name: #replyTo mailAddress: (acq name: #replyTo)
  2724.                     name: #first mailAddress: (com at: 1))]]!
  2725.  
  2726. fibonacciWaitOne
  2727.     "Answer with a Behaviour which wait for the other part of a
  2728.      fibonacci calculation."
  2729.  
  2730.     ^Behaviour block: [:slf :acq :com |
  2731.         (com name == #reply) ifTrue: [
  2732.             (acq name: #replyTo)
  2733.                 sendMessage: #reply
  2734.                 with: ((acq name: #first) + (com at: 1)).
  2735.             slf destroy]]!
  2736.  
  2737. forwarder
  2738.     "Answer with a Behaviour which forwards all communications
  2739.      to its `link' acquaintance."
  2740.  
  2741.     ^Behaviour block: [:slf :acq :com |
  2742.                     acq name: #link sendCommunication: com]!
  2743.  
  2744. rangeProduct
  2745.     "Answer with a Behaviour which answers with a product of a
  2746.      range of integers, using a recursive algorithm."
  2747.  
  2748.     | mid | 
  2749.     ^Behaviour block: [:slf :acq :com |
  2750.         (com name == #factorial) ifTrue: [
  2751.             ((com at: 1) = (com at: 2)) ifTrue: [
  2752.                 (acq name: #replyTo) sendMessage: #reply with: (com at: 1).
  2753.                 slf destroy].
  2754.             ((com at: 1) > (com at: 2)) ifTrue: [
  2755.                 (acq name: #replyTo) sendMessage: #reply with: 1.
  2756.                 slf destroy].
  2757.             ((com at: 1) < (com at: 2)) ifTrue: [
  2758.                 slf becomes: Behaviour rangeWaitBoth.
  2759.                 mid _ ((com at: 1) + (com at: 2)) // 2.
  2760.                 (Actor
  2761.                     withBehaviour: Behaviour rangeProduct
  2762.                     withAquaintances: (Aquaintances
  2763.                         name: #replyTo mailAddress: slf mailAddress))
  2764.                             sendMessage: #factorial with: (com at: 1) with: mid.
  2765.                 (Actor
  2766.                     withBehaviour: Behaviour rangeProduct
  2767.                     withAquaintances: (Aquaintances
  2768.                         name: #replyTo mailAddress: slf mailAddress))
  2769.                             sendMessage: #factorial with: (mid + 1) with: (com at: 2)]]]!
  2770.  
  2771. rangeWaitBoth
  2772.     "Answer with a Behaviour which waits for both replies to
  2773.      a range product calculation."
  2774.  
  2775.     ^Behaviour block: [:slf :acq :com |
  2776.         (com name == #reply) ifTrue: [
  2777.             slf
  2778.                 becomes: Behaviour rangeWaitOne
  2779.                 withAquaintances: (Aquaintances
  2780.                     name: #replyTo mailAddress: (acq name: #replyTo)
  2781.                     name: #first mailAddress: (com at: 1))]]!
  2782.  
  2783. rangeWaitOne
  2784.     "Answer with a Behaviour which waits for the other part of a
  2785.      range product calculation."
  2786.  
  2787.     ^Behaviour block: [:slf :acq :com |
  2788.         (com name == #reply) ifTrue: [
  2789.             (acq name: #replyTo)
  2790.                 sendMessage: #reply
  2791.                 with: ((acq name: #first) * (com at: 1)).
  2792.             slf destroy]]!
  2793.  
  2794. sink
  2795.     "Answer with a Behaviour which absorbs any incoming communications,
  2796.      and does nothing with them."
  2797.  
  2798.     ^Behaviour block: [ :slf :acq :com | "do nothing." ]!
  2799.  
  2800. stackItem
  2801.     "Answer with a Behaviour which acts as a stack item."
  2802.  
  2803.     ^Behaviour block: [:slf :acq :com |
  2804.         (com name == #show)
  2805.             ifTrue: [
  2806.                 ActorTranscript sendMessage: #cr.
  2807.                 ActorTranscript sendMessage: #show with: 'Stack item: '.
  2808.                 ActorTranscript
  2809.                     sendMessage: #show
  2810.                     with: (acq name: #count) printString.
  2811.                 slf destroy]]!
  2812.  
  2813. stackNode
  2814.     "Answer with a Behaviour which acts like a stack node."
  2815.  
  2816.     | stackBehaviour |
  2817.     stackBehaviour _ Behaviour block: [:slf :acq :com |
  2818.         (com name == #pop) & (acq name: #content) notNil ifTrue: [
  2819.             slf
  2820.                 becomes: Behaviour forwarder
  2821.                 withAquaintances: (Aquaintances
  2822.                     name: #link
  2823.                     mailAddress: (acq name: #link)).
  2824.             (com at: 1) sendMessage: #reply with: (acq name: #content)].
  2825.         (com name == #push) ifTrue: [
  2826.                 slf
  2827.                     becomes: stackBehaviour
  2828.                     withAquaintances: (Aquaintances
  2829.                             name: #link mailAddress: (Actor
  2830.                                 withBehaviour: stackBehaviour
  2831.                                 withAquaintances: (Aquaintances
  2832.                                     name: #link
  2833.                                     mailAddress: (acq name: #link)
  2834.                                     name: #content
  2835.                                     mailAddress: (acq name: #content)))
  2836.                             name: #content mailAddress: (com at: 1))]].
  2837.     ^stackBehaviour!
  2838.  
  2839. stackSink
  2840.     "Answer with a Behaviour which acts as a sink for stack items."
  2841.  
  2842.     ^Behaviour block: [ :slf :acq :com |
  2843.         (com name == #reply) ifTrue: [
  2844.             (com at: 1) sendMessage: #show]]!
  2845.  
  2846. takeuchi
  2847.     "Answer with a Behaviour which performs a takeuchi function computation."
  2848.  
  2849.     | takeuchiBehaviour    |
  2850.     takeuchiBehaviour _ Behaviour block: [ :slf :acq :com |
  2851.         (com name == #tak) ifTrue: [
  2852.             (com at: 2) >= (com at: 1)
  2853.                 ifTrue: [
  2854.                     (acq name: #replyTo) sendMessage: #reply with: (com at: 3).
  2855.                     slf destroy]
  2856.                 ifFalse: [
  2857.                     acq name: #x mailAddress: (com at: 1).
  2858.                     acq name: #y mailAddress: (com at: 2).
  2859.                     acq name: #z mailAddress: (com at: 3).
  2860.                     slf becomes: Behaviour takFirst.
  2861.                     (Actor
  2862.                         withAquaintances: (
  2863.                             Aquaintances name: #replyTo mailAddress: slf mailAddress)
  2864.                         withBehaviour: takeuchiBehaviour)
  2865.                             sendMessage: #tak
  2866.                             with: ((acq name: #x) - 1)
  2867.                             with: (acq name: #y)
  2868.                             with: (acq name: #z)]]].
  2869.     ^takeuchiBehaviour!
  2870.  
  2871. takFirst
  2872.     "Answer with a Behaviour which performs the first part of a takeuchi
  2873.      function."
  2874.  
  2875.     ^Behaviour block: [ :slf :acq :com |
  2876.         (com name == #reply) ifTrue: [
  2877.             (acq name: #replyX mailAddress: (com at: 1)).
  2878.             slf becomes: Behaviour takSecond.
  2879.             (Actor
  2880.                 withAquaintances: (
  2881.                     Aquaintances name: #replyTo mailAddress: slf mailAddress)
  2882.                 withBehaviour: Behaviour takeuchi)
  2883.                     sendMessage: #tak
  2884.                     with: ((acq name: #y) - 1)
  2885.                     with: (acq name: #z)
  2886.                     with: (acq name: #x)]]!
  2887.  
  2888. takSecond
  2889.     "Answer with a Behaviour which performs the second part of
  2890.      a takeuchi funtion."
  2891.  
  2892.     ^Behaviour block: [ :slf :acq :com |
  2893.         (com name == #reply) ifTrue: [
  2894.             (acq name: #replyY mailAddress: (com at: 1)).
  2895.             slf becomes: Behaviour takThird.
  2896.             (Actor
  2897.                 withAquaintances: (
  2898.                     Aquaintances name: #replyTo mailAddress: slf mailAddress)
  2899.                 withBehaviour: Behaviour takeuchi)
  2900.                     sendMessage: #tak
  2901.                     with: ((acq name: #z) - 1)
  2902.                     with: (acq name: #x)
  2903.                     with: (acq name: #y)]]!
  2904.  
  2905. takThird
  2906.     "Answer with a Behaviour which performs that last part of a
  2907.      takeuchi function."
  2908.  
  2909.     ^Behaviour block: [ :slf :acq :com |
  2910.         (com name == #reply) ifTrue: [
  2911.             (Actor
  2912.                 withAquaintances: (
  2913.                     Aquaintances name: #replyTo mailAddress: (acq name: #replyTo))
  2914.                 withBehaviour: Behaviour takeuchi)
  2915.                     sendMessage: #tak
  2916.                     with: (acq name: #replyX)
  2917.                     with: (acq name: #replyY)
  2918.                     with: (com at: 1).
  2919.             slf destroy]]!
  2920.  
  2921. timer
  2922.     "Answer with a Behaviour which provides timing functions.  The
  2923.      first argument in the incoming communciation is assumed to be
  2924.      a customer."
  2925.  
  2926.     ^Behaviour block: [:slf :acq :com |
  2927.         (com name == #now) ifTrue: [
  2928.             (com at: 1)
  2929.                 sendMessage: #reply
  2930.                 withArguments: (Time dateAndTimeNow)].
  2931.         (com name == #date) ifTrue: [
  2932.             (com at: 1)
  2933.                 sendMessage: #reply
  2934.                 with: (Time dateAndTimeNow at: 1)].
  2935.         (com name == #time) ifTrue: [
  2936.             (com at: 1)
  2937.                 sendMessage: #reply
  2938.                 with: (Time dateAndTimeNow at: 2)].
  2939.         (com name == #milliseconds) ifTrue: [
  2940.             (com at: 1)
  2941.                 sendMessage: #reply
  2942.                 with: (Time millisecondClockValue)]]! !
  2943.  
  2944. ActorModel subclass: #Tag
  2945.     instanceVariableNames: ''
  2946.     classVariableNames: ''
  2947.     poolDictionaries: ''
  2948.     category: 'Actors-Simulation'!
  2949. Tag comment:
  2950. 'I represent a unique identifier used to identify a Task.  Tags do not change.'!
  2951.  
  2952.  
  2953. !Tag methodsFor: 'accessing'!
  2954.  
  2955. value
  2956.     "Answer with the unique identifier represented by the receiver."
  2957.  
  2958.     ^self asOop! !
  2959.  
  2960. !Tag methodsFor: 'printing'!
  2961.  
  2962. printOn: aStream
  2963.     "Put a printable representation of the receiver on aStream."
  2964.  
  2965.     aStream nextPutAll: self value printString! !
  2966.  
  2967. ActorModel subclass: #Communication
  2968.     instanceVariableNames: 'name arguments '
  2969.     classVariableNames: ''
  2970.     poolDictionaries: ''
  2971.     category: 'Actors-Simulation'!
  2972. Communication comment:
  2973. 'I represent the content of a message (Task) sent from one Actor to
  2974. another.  Communications do not change.  My instance variables are:
  2975.  
  2976. name        <Symbol> identifying the operation intended.
  2977.  
  2978. arguments    <Array> of arguments to the operation.'!
  2979.  
  2980.  
  2981. !Communication methodsFor: 'initialize-release'!
  2982.  
  2983. release
  2984.     "Release all my instance variables."
  2985.  
  2986.     name release.
  2987.     arguments release.
  2988.     super release! !
  2989.  
  2990. !Communication methodsFor: 'accessing'!
  2991.  
  2992. arguments
  2993.     "Answer with the array of arguments of the receiver."
  2994.  
  2995.     ^arguments!
  2996.  
  2997. at: index
  2998.     "Answer with the argument at index in the argument list."
  2999.  
  3000.     ^arguments at: index!
  3001.  
  3002. name
  3003.     "Answer with the name of the receiver."
  3004.  
  3005.     ^name! !
  3006.  
  3007. !Communication methodsFor: 'printing'!
  3008.  
  3009. printOn: aStream
  3010.     "Put a printable representation of the receiver on aStream."
  3011.  
  3012.     self class name printOn: aStream.
  3013.     aStream nextPutAll: ' called '.
  3014.     name printString printOn: aStream.! !
  3015.  
  3016. !Communication methodsFor: 'inspecting'!
  3017.  
  3018. labelString
  3019.     "Answer with a string suitable for use as a view's label."
  3020.  
  3021.     ^name printString! !
  3022.  
  3023. !Communication methodsFor: 'private'!
  3024.  
  3025. setArguments: anArray
  3026.     "Set the arguments of the receiver to anArray."
  3027.  
  3028.     arguments _ anArray!
  3029.  
  3030. setName: aSymbol
  3031.     "Set the name of the receiver to aSymbol."
  3032.  
  3033.     name _ aSymbol! !
  3034. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3035.  
  3036. Communication class
  3037.     instanceVariableNames: ''!
  3038.  
  3039.  
  3040. !Communication class methodsFor: 'instance creation'!
  3041.  
  3042. name: aSymbol
  3043.     "Create a new instance of the receiver, with name aSymbol and
  3044.      no arguments."
  3045.  
  3046.     ^self name: aSymbol withArguments: #()!
  3047.  
  3048. name: aSymbol with: anArgument
  3049.     "Create a new instance of the receiver, with name aSymbol and
  3050.      one argument."
  3051.  
  3052.     ^self name: aSymbol withArguments: (Array with: anArgument)!
  3053.  
  3054. name: aSymbol with: firstArgument with: secondArgument
  3055.     "Create a new instance of the receiver, with name aSymbol and
  3056.      two arguments."
  3057.  
  3058.     ^self
  3059.         name: aSymbol
  3060.         withArguments: (Array with: firstArgument with: secondArgument)!
  3061.  
  3062. name: aSymbol with: firstArgument with: secondArgument with: thirdArgument
  3063.     "Create a new instance of the receiver, with name aSymbol and
  3064.      three arguments."
  3065.  
  3066.     ^self
  3067.         name: aSymbol
  3068.         withArguments: (Array
  3069.                             with: firstArgument
  3070.                             with: secondArgument
  3071.                             with: thirdArgument)!
  3072.  
  3073. name: aSymbol withArguments: anArray
  3074.     "Create a new instance of the receiver, with name aSymbol and
  3075.      arguments in anArray."
  3076.  
  3077.     | temp |
  3078.     temp _ self new setName: aSymbol.
  3079.     temp setArguments: anArray.
  3080.     ^temp! !
  3081.  
  3082. ActorModel subclass: #MailQueue
  3083.     instanceVariableNames: 'contents '
  3084.     classVariableNames: ''
  3085.     poolDictionaries: ''
  3086.     category: 'Actors-Simulation'!
  3087. MailQueue comment:
  3088. 'I represent a queue of messages (Tasks) sent to an actor waiting to
  3089. be processed.  An instance of me is associated with every actor.  If an
  3090. actor''s mail queue is empty, it is said to be inactive.  My instance variables:
  3091.  
  3092. contents    <ActorCollection> of Tasks, possibly empty.'!
  3093.  
  3094.  
  3095. !MailQueue methodsFor: 'initialize-release'!
  3096.  
  3097. initialize
  3098.     "Initialize the instance variable."
  3099.  
  3100.     contents _ ActorCollection new!
  3101.  
  3102. release
  3103.     "Release all my instance variables."
  3104.  
  3105.     contents release.
  3106.     super release! !
  3107.  
  3108. !MailQueue methodsFor: 'adding'!
  3109.  
  3110. addMessage: aTask
  3111.     "Add the message aTask to the end of queue represented by
  3112.      the receiver."
  3113.  
  3114.     contents addLast: aTask.
  3115.     self changed: #all! !
  3116.  
  3117. !MailQueue methodsFor: 'removing'!
  3118.  
  3119. getMessage
  3120.     "Answer with the first message (Task) in the receiver, or nil, if
  3121.      there is no message available."
  3122.  
  3123.     | message |
  3124.     contents isEmpty ifFalse: [
  3125.         message _ contents removeFirst.
  3126.         self changed: #all].
  3127.     ^message! !
  3128.  
  3129. !MailQueue methodsFor: 'testing'!
  3130.  
  3131. isEmpty
  3132.     "Answer whether the mail queue represented by the receiver is
  3133.      empty or not."
  3134.  
  3135.     ^contents isEmpty! !
  3136.  
  3137. !MailQueue methodsFor: 'printing'!
  3138.  
  3139. printOn: aStream
  3140.     "Put a printable representation of the receiver on aStream."
  3141.  
  3142.     self class name printOn: aStream.
  3143.     aStream nextPutAll: ' (', contents size printString, ')'! !
  3144. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3145.  
  3146. MailQueue class
  3147.     instanceVariableNames: ''!
  3148.  
  3149.  
  3150. !MailQueue class methodsFor: 'instance creation'!
  3151.  
  3152. new
  3153.     "Answer with a new initialized instance of the receiver."
  3154.  
  3155.     ^super new initialize! !
  3156.  
  3157. ActorModel subclass: #Task
  3158.     instanceVariableNames: 'tag target communication '
  3159.     classVariableNames: ''
  3160.     poolDictionaries: ''
  3161.     category: 'Actors-Simulation'!
  3162. Task comment:
  3163. 'I represent a message sent from one actor to another.
  3164.  
  3165. My instance variables are:
  3166.  
  3167. tag                <Tag> unique identifier for this message.
  3168.  
  3169. target            <MailAddress> of the destination actor.
  3170.  
  3171. communication    <Communication> contents of the message.'!
  3172.  
  3173.  
  3174. !Task methodsFor: 'initialize-release'!
  3175.  
  3176. initialize
  3177.     "Initialize the tag instance variable."
  3178.  
  3179.     tag _ Tag new!
  3180.  
  3181. release
  3182.     "Release the receiver's tag and communication instance variables.  Nil
  3183.      out the receiver's target, to break up possible cycles."
  3184.  
  3185.     tag release.
  3186.     target _ nil.
  3187.     communication release.
  3188.     super release! !
  3189.  
  3190. !Task methodsFor: 'accessing'!
  3191.  
  3192. communication
  3193.     "Answer with the communication of the receiver.  Used only by the interpreter."
  3194.  
  3195.     ^communication!
  3196.  
  3197. target
  3198.     "Answer with the target mail address of the receiver.  Used only
  3199.      by the interpreter."
  3200.  
  3201.     ^target! !
  3202.  
  3203. !Task methodsFor: 'sending'!
  3204.  
  3205. send
  3206.     "Send the receiver to the target."
  3207.  
  3208.     target send: self! !
  3209.  
  3210. !Task methodsFor: 'printing'!
  3211.  
  3212. printOn: aStream
  3213.     "Put a printable representation of the receiver on aStream."
  3214.  
  3215.     | addr |
  3216.     addr _ target isNil ifTrue: ['nowhere'] ifFalse: [target printString].
  3217.     self class name printOn: aStream.
  3218.     aStream nextPutAll: ' ('.
  3219.     tag printOn: aStream.
  3220.     aStream nextPutAll: ') to ', addr! !
  3221.  
  3222. !Task methodsFor: 'private'!
  3223.  
  3224. setCommunication: aCommunication
  3225.     "Set the communication of the receiver to aCommunication."
  3226.  
  3227.     communication _ aCommunication!
  3228.  
  3229. setTarget: aMailAddress
  3230.     "Set the target mail address of the receiver to aMailAddress."
  3231.  
  3232.     target _ aMailAddress! !
  3233. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3234.  
  3235. Task class
  3236.     instanceVariableNames: ''!
  3237.  
  3238.  
  3239. !Task class methodsFor: 'instance creation'!
  3240.  
  3241. communication: aCommunication target: mailAddr
  3242.     "Answer with a new instance of the receiver, with communication
  3243.      given by aCommunication, and target mailAddr."
  3244.  
  3245.     | temp |
  3246.     temp _ self new setTarget: mailAddr.
  3247.     temp setCommunication: aCommunication.
  3248.     ^temp!
  3249.  
  3250. new
  3251.     "Answer with a new initialised instance of the receiver."
  3252.  
  3253.     ^super new initialize! !
  3254.  
  3255.  
  3256. Object subclass: #RecursiveFactorial
  3257.     instanceVariableNames: ''
  3258.     classVariableNames: ''
  3259.     poolDictionaries: ''
  3260.     category: 'Actors-Smalltalk examples'!
  3261. RecursiveFactorial comment:
  3262. 'I represent a factorial calculator, using a recursive algorithm.'!
  3263.  
  3264.  
  3265. !RecursiveFactorial methodsFor: 'factorial'!
  3266.  
  3267. factorial: n
  3268.     "Perform a recursive factorial computation."
  3269.  
  3270.     n <= 1
  3271.         ifTrue: [^n]
  3272.         ifFalse: [^n * (self factorial: (n - 1))]! !
  3273. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3274.  
  3275. RecursiveFactorial class
  3276.     instanceVariableNames: ''!
  3277.  
  3278.  
  3279. !RecursiveFactorial class methodsFor: 'examples'!
  3280.  
  3281. example1
  3282.     "RecursiveFactorial example1."
  3283.  
  3284.     Transcript cr; show: (RecursiveFactorial new factorial: 20) printString!
  3285.  
  3286. example2
  3287.     "RecursiveFactorial example2."
  3288.  
  3289.     | fac |
  3290.     fac _ RecursiveFactorial new.
  3291.     Transcript cr; show: (Time millisecondsToRun: [
  3292.         1000 timesRepeat: [fac factorial: 20]]) printString! !
  3293.  
  3294. Object subclass: #DivideAndConquerFactorial
  3295.     instanceVariableNames: ''
  3296.     classVariableNames: ''
  3297.     poolDictionaries: ''
  3298.     category: 'Actors-Smalltalk examples'!
  3299. DivideAndConquerFactorial comment:
  3300. 'I represent a factorial computation, using a doubly recursive
  3301. `divide-and-conquer'' algorithm.'!
  3302.  
  3303.  
  3304. !DivideAndConquerFactorial methodsFor: 'factorial'!
  3305.  
  3306. factorial: n
  3307.     "Answer with n factorial, using a recursive divide-and-conquer algorithm."
  3308.  
  3309.     ^self rangeProductLow: 1 high: n!
  3310.  
  3311. rangeProductLow: lo high: hi
  3312.     "Answer with the product of the numbers between lo and hi."
  3313.  
  3314.     | mid |
  3315.     (lo = hi) ifTrue: [^lo].
  3316.     (lo > hi) ifTrue: [^1].
  3317.     (lo < hi) ifTrue: [
  3318.         mid _ (lo + hi ) // 2.
  3319.         ^(self rangeProductLow: lo high: mid) * (self rangeProductLow: mid + 1 high: hi)]! !
  3320. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3321.  
  3322. DivideAndConquerFactorial class
  3323.     instanceVariableNames: ''!
  3324.  
  3325.  
  3326. !DivideAndConquerFactorial class methodsFor: 'examples'!
  3327.  
  3328. example1
  3329.     "DivideAndConquerFactorial example1."
  3330.  
  3331.     Transcript cr; show: (DivideAndConquerFactorial new factorial: 20) printString!
  3332.  
  3333. example2
  3334.     "DivideAndConquerFactorial example2."
  3335.  
  3336.     | fac |
  3337.     fac _ DivideAndConquerFactorial new.
  3338.     Transcript cr; show: (Time millisecondsToRun: [
  3339.         1000 timesRepeat: [fac factorial: 20]]) printString! !
  3340.  
  3341. Object subclass: #IterativeFactorial
  3342.     instanceVariableNames: 'current '
  3343.     classVariableNames: ''
  3344.     poolDictionaries: ''
  3345.     category: 'Actors-Smalltalk examples'!
  3346. IterativeFactorial comment:
  3347. 'I represent a factorial calculator, using an interative algorithm.'!
  3348.  
  3349.  
  3350. !IterativeFactorial methodsFor: 'factorial'!
  3351.  
  3352. factorial: n
  3353.     "Perform an iterative factorial computation."
  3354.  
  3355.     current _ 1.
  3356.     ^self iterate: n!
  3357.  
  3358. iterate: n 
  3359.     "Perform an iterative factorial step."
  3360.  
  3361.     (n <= 1)
  3362.         ifTrue: [^current]
  3363.         ifFalse: [
  3364.             current _ current * n.
  3365.             ^self iterate: (n - 1)]! !
  3366. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3367.  
  3368. IterativeFactorial class
  3369.     instanceVariableNames: ''!
  3370.  
  3371.  
  3372. !IterativeFactorial class methodsFor: 'examples'!
  3373.  
  3374. example1
  3375.     "IterativeFactorial example1."
  3376.  
  3377.     Transcript cr; show: (IterativeFactorial new factorial: 20) printString.!
  3378.  
  3379. example2
  3380.     "IterativeFactorial example2."
  3381.  
  3382.     | fac |
  3383.     fac _ IterativeFactorial new.
  3384.     Transcript cr; show: (fac factorial: 3) printString.
  3385.     Transcript cr; show: (fac factorial: 10) printString!
  3386.  
  3387. example3
  3388.     "IterativeFactorial example3."
  3389.  
  3390.     | fac |
  3391.     fac _ IterativeFactorial new.
  3392.     Transcript cr; show: (Time millisecondsToRun: [
  3393.         1000 timesRepeat: [fac factorial: 20]]) printString! !
  3394.  
  3395. Object subclass: #Surrogate
  3396.     instanceVariableNames: 'proxy '
  3397.     classVariableNames: ''
  3398.     poolDictionaries: ''
  3399.     category: 'Actors-Smalltalk examples'!
  3400. Surrogate comment:
  3401. 'I represent a simple implementation of surrogates.'!
  3402.  
  3403.  
  3404. !Surrogate methodsFor: 'synchronising'!
  3405.  
  3406. doesNotUnderstand: aMessage
  3407.     "Any message to a Surrogate will end up here."
  3408.  
  3409.     ^proxy perform: aMessage selector withArguments: aMessage arguments! !
  3410.  
  3411. !Surrogate methodsFor: 'private'!
  3412.  
  3413. setProxy: anObject
  3414.     "Set the proxy to be anObject."
  3415.  
  3416.     proxy _ anObject! !
  3417. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3418.  
  3419. Surrogate class
  3420.     instanceVariableNames: ''!
  3421.  
  3422.  
  3423. !Surrogate class methodsFor: 'instance creation'!
  3424.  
  3425. newOn: anObject
  3426.     "Create a new instance of the receiver, being a surrogate for anObject."
  3427.  
  3428.     ^self new setProxy: anObject! !
  3429.  
  3430. !Surrogate class methodsFor: 'class initialization'!
  3431.  
  3432. initialize
  3433.      "must avoid the checks"
  3434.  
  3435.     superclass _ nil
  3436.  
  3437.     "Surrogate initialize."! !
  3438.  
  3439. Surrogate initialize!
  3440.  
  3441.  
  3442. Object subclass: #Takeuchi
  3443.     instanceVariableNames: 'counter '
  3444.     classVariableNames: ''
  3445.     poolDictionaries: ''
  3446.     category: 'Actors-Smalltalk examples'!
  3447.  
  3448.  
  3449. !Takeuchi methodsFor: 'initialize-release'!
  3450.  
  3451. initialize
  3452.     "Zero the counter."
  3453.  
  3454.     counter _ 0.! !
  3455.  
  3456. !Takeuchi methodsFor: 'accessing'!
  3457.  
  3458. count
  3459.     "Answer with the counter value."
  3460.  
  3461.     ^counter! !
  3462.  
  3463. !Takeuchi methodsFor: 'takeuchi'!
  3464.  
  3465. takeuchiWith: x with: y with: z
  3466.     "Answer with the takeuchi function of x, y and z."
  3467.     "Takeuchi new takeuchiWith: 3 with: 2 with: 1."
  3468.  
  3469.     counter _ counter + 1.
  3470.     (y >= x) ifTrue: [^z] ifFalse: [
  3471.         ^self
  3472.             takeuchiWith: (self takeuchiWith: (x-1) with: y with: z)
  3473.             with: (self takeuchiWith: (y-1) with: z with: x)
  3474.             with: (self takeuchiWith: (z-1) with: x with: y)]!
  3475.  
  3476. tracedTakeuchiWith: x with: y with: z
  3477.     "Answer with the takeuchi function of x, y and z."
  3478.     "Takeuchi new tracedTakeuchiWith: 3 with: 2 with: 1."
  3479.  
  3480.     counter _ counter + 1.
  3481.     Transcript
  3482.         cr; show: x printString;
  3483.         space; show: y printString;
  3484.         space; show: z printString.
  3485.     (y >= x) ifTrue: [^z] ifFalse: [
  3486.         ^self
  3487.             tracedTakeuchiWith: (self tracedTakeuchiWith: (x-1) with: y with: z)
  3488.             with: (self tracedTakeuchiWith: (y-1) with: z with: x)
  3489.             with: (self tracedTakeuchiWith: (z-1) with: x with: y)]! !
  3490. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3491.  
  3492. Takeuchi class
  3493.     instanceVariableNames: ''!
  3494.  
  3495.  
  3496. !Takeuchi class methodsFor: 'instance creation'!
  3497.  
  3498. new
  3499.     "Create an initialized instnace of the receiver."
  3500.  
  3501.     ^super new initialize! !
  3502.  
  3503.  
  3504. TextCollector subclass: #ActorTextCollector
  3505.     instanceVariableNames: ''
  3506.     classVariableNames: 'DefaultBehaviour TheTextCollector '
  3507.     poolDictionaries: ''
  3508.     category: 'Actors-Interface'!
  3509. ActorTextCollector comment:
  3510. 'I support special instance creation methods for a `transcript'' for actors.'!
  3511.  
  3512. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3513.  
  3514. ActorTextCollector class
  3515.     instanceVariableNames: ''!
  3516.  
  3517.  
  3518. !ActorTextCollector class methodsFor: 'actor creation'!
  3519.  
  3520. newTranscript
  3521.     "Create a global Actor called ActorTranscript, which behaves as
  3522.      a transcript for actors."
  3523.     "ActorTextCollector newTranscript."
  3524.  
  3525.     self newTranscript: DefaultBehaviour!
  3526.  
  3527. newTranscript: behaviour
  3528.     "Create a global Actor which behaves as a transcript, with
  3529.      behaviour from the argument."
  3530.     "ActorTextCollector newTranscript: ActorTextCollector defaultBehaviour."
  3531.  
  3532.     Smalltalk at: #ActorTranscript put: (Actor withBehaviour: behaviour).!
  3533.  
  3534. open
  3535.     "Create and schedule a view on my global instance."
  3536.     "ActorTextCollector open."
  3537.  
  3538.     TextCollectorView open: TheTextCollector label: 'Actor (', ActorTranscript printString, ') Transcript'! !
  3539.  
  3540. !ActorTextCollector class methodsFor: 'class initialization'!
  3541.  
  3542. initialize
  3543.     "Set up the Actor Transcript."
  3544.     "ActorTextCollector initialize."
  3545.  
  3546.     self setTranscript!
  3547.  
  3548. setTranscript
  3549.     "Initialize the class variables."
  3550.  
  3551.     TheTextCollector _ self new.
  3552.     DefaultBehaviour _ Behaviour block: [:slf :acq :com | 
  3553.         com name == #cr ifTrue: [TheTextCollector cr].
  3554.         com name == #tab ifTrue: [TheTextCollector tab].
  3555.         com name == #show ifTrue: [
  3556.                     TheTextCollector show: (com at: 1)].
  3557.         com name == #clear ifTrue: [TheTextCollector clear].
  3558.         com name == #flash ifTrue: [TheTextCollector flash; refresh]]! !
  3559.  
  3560. !ActorTextCollector class methodsFor: 'class access'!
  3561.  
  3562. defaultBehaviour
  3563.     "Answer with the class variable representing the default behaviour
  3564.      of instances of the receiver."
  3565.     "ActorTextCollector defaultBehaviour."
  3566.  
  3567.     ^DefaultBehaviour! !
  3568.  
  3569. !ActorTextCollector class methodsFor: 'examples'!
  3570.  
  3571. example1
  3572.     "ActorTextCollector example1."
  3573.  
  3574.     ActorTranscript sendMessage: #cr.
  3575.     ActorTranscript sendMessage: #show with: 'Hello world!!'.!
  3576.  
  3577. example2
  3578.     "ActorTextCollector example2."
  3579.  
  3580.     ActorTranscript sendMessage: #clear.
  3581.     ActorTranscript sendMessage: #show with: 'Hello again!!'.
  3582.     ActorTranscript sendMessage: #flash.!
  3583.  
  3584. example3
  3585.     "ActorTextCollector example3."
  3586.  
  3587.     ActorTranscript sendMessage: #clear.
  3588.     ActorTranscript sendMessage: #show with: 'First Message, '.
  3589.     ActorTranscript sendMessage: #show with: 'Second Message '.
  3590.     ActorTranscript sendMessage: #show with: 'and Third Message'.! !
  3591.  
  3592. ActorTextCollector initialize!
  3593.